int Ns_ConnFlush(Ns_Conn *conn, char *buf, int len, int stream) { Conn *connPtr = (Conn *) conn; NsServer *servPtr = connPtr->servPtr; Tcl_Encoding encoding; Tcl_DString enc, gzip; char *ahdr; int status; connPtr->sbuf=buf; if (NsRunFilters((Ns_Conn *) connPtr, NS_FILTER_PRE_WRITE) != NS_OK) { return NS_ERROR; } if (connPtr->rbuf != NULL) { /* the content was set by pre-write filters */ buf=Tcl_DStringValue(connPtr->rbuf); len=Tcl_DStringLength(connPtr->rbuf); } Tcl_DStringInit(&enc); Tcl_DStringInit(&gzip); if (len < 0) { len = strlen(buf); } /* * Encode content to the expected charset. */ encoding = Ns_ConnGetEncoding(conn); if (encoding != NULL) { Tcl_UtfToExternalDString(encoding, buf, len, &enc); buf = enc.string; len = enc.length; } /* * GZIP the content when not streaming if enabled and the content * length is above the minimum. */ if (!stream && (conn->flags & NS_CONN_GZIP) && (servPtr->opts.flags & SERV_GZIP) && (len > (int) servPtr->opts.gzipmin) && (ahdr = Ns_SetIGet(conn->headers, "Accept-Encoding")) != NULL && strstr(ahdr, "gzip") != NULL && Ns_Gzip(buf, len, servPtr->opts.gziplevel, &gzip) == NS_OK) { buf = gzip.string; len = gzip.length; Ns_ConnCondSetHeaders(conn, "Content-Encoding", "gzip"); } /* * Flush content. */ status = Ns_ConnFlushDirect(conn, buf, len, stream); Tcl_DStringFree(&enc); Tcl_DStringFree(&gzip); return status; }
int Ns_ConnSend(Ns_Conn *conn, struct iovec *bufs, int nbufs) { Conn *connPtr = (Conn *) conn; int nwrote, towrite, i, n; struct iovec sbufs[16]; /* * Send up to 16 buffers, including the queued output * buffer if necessary. */ towrite = 0; n = 0; if (connPtr->obuf.length > 0) { sbufs[n].iov_base = connPtr->obuf.string; sbufs[n].iov_len = connPtr->obuf.length; towrite += sbufs[n].iov_len; ++n; } for (i = 0; i < nbufs && n < 16; ++i) { if (bufs[i].iov_len > 0 && bufs[i].iov_base != NULL) { sbufs[n].iov_base = bufs[i].iov_base; sbufs[n].iov_len = bufs[i].iov_len; towrite += bufs[i].iov_len; ++n; } } nbufs = n; bufs = sbufs; n = nwrote = 0; while (towrite > 0) { n = NsConnSend(conn, bufs, nbufs); if (n < 0) { break; } towrite -= n; nwrote += n; if (towrite > 0) { for (i = 0; i < nbufs && n > 0; ++i) { if (n > (int) bufs[i].iov_len) { n -= bufs[i].iov_len; bufs[i].iov_base = NULL; bufs[i].iov_len = 0; } else { bufs[i].iov_base = (char *) bufs[i].iov_base + n; bufs[i].iov_len -= n; n = 0; } } } } if (nwrote > 0) { connPtr->nContentSent += nwrote; if (connPtr->obuf.length > 0) { n = connPtr->obuf.length - nwrote; if (n <= 0) { nwrote -= connPtr->obuf.length; Tcl_DStringTrunc(&connPtr->obuf, 0); } else { memmove(connPtr->obuf.string, connPtr->obuf.string + nwrote, (size_t)n); Tcl_DStringTrunc(&connPtr->obuf, n); nwrote = 0; } } } else { /* * Return error on first send, if any, from NsSockSend above. */ nwrote = n; } if (nwrote >= 0 && NsRunFilters((Ns_Conn *) connPtr, NS_FILTER_WRITE) != NS_OK) { nwrote = -1; } return nwrote; }
static void ConnRun(Conn *connPtr) { Tcl_Encoding encoding = NULL; Ns_Conn *conn = (Ns_Conn *) connPtr; NsServer *servPtr = connPtr->servPtr; int i, status; /* * Initialize the connection encodings. */ encoding = NsGetInputEncoding(connPtr); if (encoding == NULL) { encoding = NsGetOutputEncoding(connPtr); if (encoding == NULL) { encoding = connPtr->servPtr->urlEncoding; } } Ns_ConnSetUrlEncoding((Ns_Conn *) connPtr, encoding); if (connPtr->servPtr->opts.hdrcase != Preserve) { for (i = 0; i < Ns_SetSize(connPtr->headers); ++i) { if (connPtr->servPtr->opts.hdrcase == ToLower) { Ns_StrToLower(Ns_SetKey(connPtr->headers, i)); } else { Ns_StrToUpper(Ns_SetKey(connPtr->headers, i)); } } } /* * Run the request. */ if (connPtr->request->protocol != NULL && connPtr->request->host != NULL) { status = NsConnRunProxyRequest((Ns_Conn *) connPtr); } else { status = NsRunFilters(conn, NS_FILTER_PRE_AUTH); if (status == NS_OK) { status = Ns_AuthorizeRequest(servPtr->server, connPtr->request->method, connPtr->request->url, connPtr->authUser, connPtr->authPasswd, connPtr->peer); switch (status) { case NS_OK: status = NsRunFilters(conn, NS_FILTER_POST_AUTH); if (status == NS_OK) { status = Ns_ConnRunRequest(conn); } break; case NS_FORBIDDEN: Ns_ConnReturnForbidden(conn); break; case NS_UNAUTHORIZED: Ns_ConnReturnUnauthorized(conn); break; case NS_ERROR: default: Ns_ConnReturnInternalError(conn); break; } } else if (status != NS_FILTER_RETURN) { /* if not ok or filter_return, then the pre-auth filter coughed * an error. We are not going to proceed, but also we * can't count on the filter to have sent a response * back to the client. So, send an error response. */ Ns_ConnReturnInternalError(conn); status = NS_FILTER_RETURN; /* to allow tracing to happen */ } } Ns_ConnClose(conn); if (status == NS_OK || status == NS_FILTER_RETURN) { status = NsRunFilters(conn, NS_FILTER_TRACE); if (status == NS_OK) { (void) NsRunFilters(conn, NS_FILTER_VOID_TRACE); NsRunTraces(conn); } } /* * Cleanup the connections, calling any registered cleanup traces * followed by free the connection interp if it was used. */ NsRunCleanups(conn); NsFreeConnInterp(connPtr); }