From: Vlad S. <ser...@us...> - 2005-07-10 07:27:22
|
Update of /cvsroot/naviserver/naviserver/nsd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29430/nsd Modified Files: conn.c connio.c fastpath.c return.c Log Message: See ChangeLog Index: fastpath.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/fastpath.c,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** fastpath.c 9 Jul 2005 02:16:30 -0000 1.17 --- fastpath.c 10 Jul 2005 07:27:13 -0000 1.18 *************** *** 866,874 **** return Ns_ConnReturnOpenFd(conn, rnPtr->status, type, fd, len); } ! Ns_ConnSetRequiredHeaders(conn, type, len); ! Ns_ConnQueueHeaders(conn, rnPtr->status); ! bufs[0].iov_base = data; ! bufs[0].iov_len = len; ! result = Ns_ConnSend(conn, bufs, 1); break; --- 866,870 ---- return Ns_ConnReturnOpenFd(conn, rnPtr->status, type, fd, len); } ! result = Ns_ConnReturnData(conn, rnPtr->status, data, len, type); break; *************** *** 878,882 **** * included in the reply */ - Ns_ConnPrintfHeaders(conn, "Content-range", "bytes %lu-%lu/%i", rnPtr->offsets[0].start, rnPtr->offsets[0].end, len); --- 874,877 ---- *************** *** 887,893 **** Ns_ConnSetRequiredHeaders(conn, type, rnPtr->offsets[0].size); Ns_ConnQueueHeaders(conn, rnPtr->status); ! bufs[0].iov_base = data + rnPtr->offsets[0].start; ! bufs[0].iov_len = rnPtr->offsets[0].size; ! result = Ns_ConnSend(conn, bufs, 1); break; --- 882,888 ---- Ns_ConnSetRequiredHeaders(conn, type, rnPtr->offsets[0].size); Ns_ConnQueueHeaders(conn, rnPtr->status); ! iovPtr->iov_base = data + rnPtr->offsets[0].start; ! iovPtr->iov_len = rnPtr->offsets[0].size; ! result = Ns_ConnSend(conn, iovPtr, 1); break; Index: return.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/return.c,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** return.c 6 Jul 2005 09:15:44 -0000 1.11 --- return.c 10 Jul 2005 07:27:13 -0000 1.12 *************** *** 159,185 **** } - static int - IsSetupForChunkedEncoding(Ns_Conn *conn) - { - int headerCount = 0; - int i; - Ns_Set* outHeaders; - - if (conn == NULL) - return 0; - - outHeaders = Ns_ConnOutputHeaders(conn); - headerCount = Ns_SetSize (outHeaders); - - if (outHeaders && headerCount) { - for (i = 0 ; i < headerCount ; i++) { - if ( !strcasecmp(Ns_SetKey (outHeaders, i), HTTP11_HDR_TE) && - !strcasecmp(Ns_SetValue (outHeaders, i), HTTP11_TE_CHUNKED) ) - return 1; - } - } - return 0; - } - /* --- 159,162 ---- *************** *** 191,195 **** * * Results: ! * None. * * Side effects: --- 168,172 ---- * * Results: ! * None. * * Side effects: *************** *** 209,213 **** char *value, *keep; char *key, *lengthHdr; - int doChunkEncoding = 0; /* --- 186,189 ---- *************** *** 222,229 **** } } ! doChunkEncoding = IsSetupForChunkedEncoding(conn); Ns_DStringPrintf(dsPtr, "HTTP/%s %d %s\r\n", ! doChunkEncoding ? "1.1" : "1.0", connPtr->responseStatus, reason); --- 198,226 ---- } } ! ! /* ! * Perform some checks to ensure proper use of chunked ! * encoding ! */ ! ! if ((connPtr->responseStatus == 204 || ! connPtr->responseStatus == 206 || ! connPtr->responseStatus == 304)) { ! conn->flags &= ~NS_CONN_CHUNKED; ! Ns_SetIDeleteKey(conn->outputheaders, "Transfer-encoding"); ! } ! ! /* ! * This connection has been marked to return in chunked encoding ! */ ! ! if (conn->flags & NS_CONN_CHUNKED) { ! Ns_ConnCondSetHeaders(conn, "Transfer-encoding", "chunked"); ! Ns_SetIDeleteKey(conn->outputheaders, "Content-length"); ! connPtr->responseLength = 0; ! } Ns_DStringPrintf(dsPtr, "HTTP/%s %d %s\r\n", ! (conn->flags & NS_CONN_CHUNKED) ? "1.1" : "1.0", connPtr->responseStatus, reason); *************** *** 255,262 **** connPtr->headers != NULL && connPtr->request != NULL && ! (( (connPtr->responseStatus >= 200 && connPtr->responseStatus < 300) && ! ((lengthHdr != NULL && ! connPtr->responseLength == length) || doChunkEncoding)) || ! (connPtr->responseStatus == 304 || connPtr->responseStatus == 201 || connPtr->responseStatus == 207) ) && (drvPtr->keepallmethods == NS_TRUE || STREQ(connPtr->request->method, "GET")) && --- 252,261 ---- connPtr->headers != NULL && connPtr->request != NULL && ! (((connPtr->responseStatus >= 200 && connPtr->responseStatus < 300) && ! ((lengthHdr != NULL && connPtr->responseLength == length) || ! (conn->flags & NS_CONN_CHUNKED)) ) || ! (connPtr->responseStatus == 304 || ! connPtr->responseStatus == 201 || ! connPtr->responseStatus == 207) ) && (drvPtr->keepallmethods == NS_TRUE || STREQ(connPtr->request->method, "GET")) && *************** *** 339,343 **** { Ns_ConnQueueHeaders(conn, status); ! return Ns_WriteConn(conn, NULL, 0); } --- 338,342 ---- { Ns_ConnQueueHeaders(conn, status); ! return Ns_ConnSend(conn, NULL, 0); } *************** *** 825,828 **** --- 824,838 ---- result = Ns_WriteConn(conn, data, len); if (result == NS_OK) { + + /* + * In chunked mode we must send the last chunk with zero size + */ + + if (len > 0 && (conn->flags & NS_CONN_CHUNKED)) { + result = Ns_WriteConn(conn, 0, 0); + } + } + + if (result == NS_OK) { result = Ns_ConnClose(conn); } Index: connio.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/connio.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** connio.c 9 Jul 2005 02:16:30 -0000 1.5 --- connio.c 10 Jul 2005 07:27:13 -0000 1.6 *************** *** 219,223 **** * * Side effects: ! * Stuff may be written * *---------------------------------------------------------------------- --- 219,224 ---- * * Side effects: ! * Stuff may be written. In chunked mode writing 0 bytes means ! * terminating chunked stream with zero chunk and ending CRLF * *---------------------------------------------------------------------- *************** *** 227,235 **** Ns_ConnWrite(Ns_Conn *conn, void *vbuf, int towrite) { ! struct iovec buf; ! buf.iov_base = vbuf; ! buf.iov_len = towrite; ! return Ns_ConnSend(conn, &buf, 1); } --- 228,264 ---- Ns_ConnWrite(Ns_Conn *conn, void *vbuf, int towrite) { ! int nsend; ! char hdr[32]; ! struct iovec buf[3]; ! if (!(conn->flags & NS_CONN_CHUNKED)) { ! ! buf[0].iov_base = vbuf; ! buf[0].iov_len = towrite; ! return Ns_ConnSend(conn, buf, 1); ! } ! ! /* ! * Send data as chunked: size CRLF data CRLF ! */ ! ! buf[0].iov_base = hdr; ! buf[0].iov_len = sprintf(hdr, "%x\r\n", towrite); ! buf[1].iov_base = vbuf; ! buf[1].iov_len = towrite; ! buf[2].iov_base = "\r\n"; ! buf[2].iov_len = 2; ! ! nsend = Ns_ConnSend(conn, buf, 3); ! ! /* ! * In chunked mode we actually sent more data ! * but Ns_WriteConn does not know about that ! */ ! ! if (nsend == buf[0].iov_len + buf[1].iov_len + buf[2].iov_len) { ! nsend = towrite; ! } ! return nsend; } *************** *** 404,410 **** *---------------------------------------------------------------------- * ! * Ns_ConnSendChannel, Fp, Fd -- * ! * Send an open channel, FILE, or fd. * * Results: --- 433,439 ---- *---------------------------------------------------------------------- * ! * Ns_ConnSendChannel, Fp, Fd, Buf -- * ! * Send an open channel, FILE, fd or memory buffer. * * Results: *************** *** 769,785 **** static int ! ConnSend(Ns_Conn *conn, int nsend, Tcl_Channel chan, FILE *fp, int fd) { ! int toread, nread, status; char buf[IOBUFSZ]; ! /* ! * Even if nsend is 0, ensure all queued data (like HTTP response ! * headers) get flushed. ! */ ! if (nsend == 0) { ! Ns_WriteConn(conn, NULL, 0); ! } ! status = NS_OK; while (status == NS_OK && nsend > 0) { --- 798,807 ---- static int ! ConnSend(Ns_Conn *conn, int tosend, Tcl_Channel chan, FILE *fp, int fd) { ! int nsend, toread, nread, status; char buf[IOBUFSZ]; ! nsend = tosend; status = NS_OK; while (status == NS_OK && nsend > 0) { *************** *** 807,810 **** --- 829,841 ---- } + /* + * Even if nsend is 0, ensure all queued data (like HTTP response + * headers) get flushed. + * In chunked mode we must send the last chunk with zero size + */ + + if (tosend == 0 || (conn->flags & NS_CONN_CHUNKED)) { + Ns_WriteConn(conn, 0, 0); + } return status; } Index: conn.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/conn.c,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** conn.c 30 Jun 2005 07:57:41 -0000 1.18 --- conn.c 10 Jul 2005 07:27:13 -0000 1.19 *************** *** 868,871 **** --- 868,920 ---- } + /* + *---------------------------------------------------------------------- + * + * Ns_ConnGetChunkedFlag -- + * + * Is the given connection set for chunked encoded writes. + * + * Results: + * Boolean + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + + int + Ns_ConnGetChunkedFlag(Ns_Conn *conn) + { + return (conn->flags & NS_CONN_CHUNKED) ? NS_TRUE : NS_FALSE; + } + + + /* + *---------------------------------------------------------------------- + * + * Ns_ConnSetChunkedFlag -- + * + * Set the given connection chunked encoding flag per parameter. + * + * Results: + * None + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + + void + Ns_ConnSetChunkedFlag(Ns_Conn *conn, int flag) + { + if (flag) { + conn->flags |= NS_CONN_CHUNKED; + } else { + conn->flags &= ~NS_CONN_CHUNKED; + } + } + /* *************** *** 910,913 **** --- 959,963 ---- "query", "request", "server", "sock", "start", "status", "url", "urlc", "urlencoding", "urlv", "version", "write_encoded", + "chunked", NULL }; *************** *** 920,924 **** CPeerPortIdx, CPortIdx, CProtocolIdx, CQueryIdx, CRequestIdx, CServerIdx, CSockIdx, CStartIdx, CStatusIdx, CUrlIdx, ! CUrlcIdx, CUrlEncodingIdx, CUrlvIdx, CVersionIdx, CWriteEncodedIdx }; --- 970,975 ---- CPeerPortIdx, CPortIdx, CProtocolIdx, CQueryIdx, CRequestIdx, CServerIdx, CSockIdx, CStartIdx, CStatusIdx, CUrlIdx, ! CUrlcIdx, CUrlEncodingIdx, CUrlvIdx, CVersionIdx, CWriteEncodedIdx, ! CChunkedIdx }; *************** *** 1147,1150 **** --- 1198,1218 ---- break; + case CChunkedIdx: + if (objc > 2) { + int chunked_flag; + if (Tcl_GetIntFromObj(interp, objv[2], &chunked_flag) + != TCL_OK) { + Tcl_AppendResult(interp, "Invalid chunked flag", NULL ); + return TCL_ERROR; + } + Ns_ConnSetChunkedFlag(conn, chunked_flag); + } + if (Ns_ConnGetChunkedFlag(conn)) { + Tcl_SetIntObj(result, 1); + } else { + Tcl_SetIntObj(result, 0); + } + break; + case CRequestIdx: Tcl_SetResult(interp, request->line, TCL_STATIC); |