=== modified file 'src/MemBuf.cc' --- src/MemBuf.cc 2012-11-28 01:13:21 +0000 +++ src/MemBuf.cc 2013-10-16 11:56:06 +0000 @@ -259,7 +259,9 @@ grow(size + sz + 1); assert(size + sz <= capacity); /* paranoid */ - memcpy(space(), newContent, sz); + // memmove() allows memory blocks to overlap + // we do assume it handles space()==newContent efficiently + memmove(space(), newContent, sz); appended(sz); } PROF_stop(MemBuf_append); === modified file 'src/acl/DestinationIp.cc' --- src/acl/DestinationIp.cc 2013-05-13 23:32:23 +0000 +++ src/acl/DestinationIp.cc 2013-10-13 08:28:30 +0000 @@ -57,8 +57,8 @@ // To resolve this we will force DIRECT and only to the original client destination. // In which case, we also need this ACL to accurately match the destination if (Config.onoff.client_dst_passthru && (checklist->request->flags.intercepted || checklist->request->flags.interceptTproxy)) { - assert(checklist->conn() && checklist->conn()->clientConnection != NULL); - return ACLIP::match(checklist->conn()->clientConnection->local); + assert(checklist->conn() && checklist->conn()->tcp != NULL); + return ACLIP::match(checklist->conn()->tcp->local); } if (flags.isSet(ACL_F_NO_LOOKUP)) { === modified file 'src/acl/FilledChecklist.cc' --- src/acl/FilledChecklist.cc 2013-10-25 00:13:46 +0000 +++ src/acl/FilledChecklist.cc 2013-10-29 02:33:43 +0000 @@ -79,13 +79,13 @@ int ACLFilledChecklist::fd() const { - return (conn_ != NULL && conn_->clientConnection != NULL) ? conn_->clientConnection->fd : fd_; + return (conn_ != NULL && conn_->tcp != NULL) ? conn_->tcp->fd : fd_; } void ACLFilledChecklist::fd(int aDescriptor) { - assert(!conn() || conn()->clientConnection == NULL || conn()->clientConnection->fd == aDescriptor); + assert(!conn() || conn()->tcp == NULL || conn()->tcp->fd == aDescriptor); fd_ = aDescriptor; } === modified file 'src/auth/UserRequest.cc' --- src/auth/UserRequest.cc 2013-11-11 11:24:23 +0000 +++ src/auth/UserRequest.cc 2013-11-19 22:38:24 +0000 @@ -352,7 +352,7 @@ if (*auth_user_request == NULL) { if (conn != NULL) { - debugs(29, 9, HERE << "This is a new checklist test on:" << conn->clientConnection); + debugs(29, 9, "This is a new checklist test on:" << conn->tcp); } if (proxy_auth && request->auth_user_request == NULL && conn != NULL && conn->getAuth() != NULL) { === modified file 'src/client_side.cc' --- src/client_side.cc 2013-11-23 00:58:42 +0000 +++ src/client_side.cc 2013-11-25 23:03:45 +0000 @@ -228,7 +228,6 @@ static void clientUpdateSocketStats(LogTags logType, size_t size); char *skipLeadingSpace(char *aString); -static void connNoteUseOfBuffer(ConnStateData* conn, size_t byteCount); clientStreamNode * ClientSocketContext::getTail() const @@ -245,26 +244,6 @@ return (clientStreamNode *)http->client_stream.tail->prev->data; } -/** - * This routine should be called to grow the inbuf and then - * call comm_read(). - */ -void -ConnStateData::readSomeData() -{ - if (reading()) - return; - - debugs(33, 4, HERE << clientConnection << ": reading request..."); - - if (!maybeMakeSpaceAvailable()) - return; - - typedef CommCbMemFunT Dialer; - reader = JobCallback(33, 5, Dialer, this, ConnStateData::clientReadRequest); - comm_read(clientConnection, in.addressToReadInto(), getAvailableBufferLength(), reader); -} - void ClientSocketContext::removeFromConnectionList(ConnStateData * conn) { @@ -421,7 +400,7 @@ clientIdentDone(const char *ident, void *data) { ConnStateData *conn = (ConnStateData *)data; - xstrncpy(conn->clientConnection->rfc931, ident ? ident : dash_str, USER_IDENT_SZ); + xstrncpy(conn->tcp->rfc931, ident ? ident : dash_str, USER_IDENT_SZ); } #endif @@ -654,8 +633,8 @@ if (request) prepareLogWithRequestDetails(request, al); - if (getConn() != NULL && getConn()->clientConnection != NULL && getConn()->clientConnection->rfc931[0]) - al->cache.rfc931 = getConn()->clientConnection->rfc931; + if (getConn() != NULL && getConn()->tcp != NULL && getConn()->tcp->rfc931[0]) + al->cache.rfc931 = getConn()->tcp->rfc931; #if USE_SSL && 0 @@ -705,8 +684,8 @@ if (request) updateCounters(); - if (getConn() != NULL && getConn()->clientConnection != NULL) - clientdbUpdate(getConn()->clientConnection->remote, logType, AnyP::PROTO_HTTP, out.size); + if (getConn() != NULL && getConn()->tcp != NULL) + clientdbUpdate(getConn()->tcp->remote, logType, AnyP::PROTO_HTTP, out.size); } } @@ -762,26 +741,20 @@ /// propagates abort event to all contexts void -ConnStateData::notifyAllContexts(int xerrno) +ConnStateData::noteTcpReadError(int xerrno) { typedef ClientSocketContext::Pointer CSCP; for (CSCP c = getCurrentContext(); c.getRaw(); c = c->next) c->noteIoError(xerrno); } -/* This is a handler normally called by comm_close() */ -void ConnStateData::connStateClosed(const CommCloseCbParams &io) -{ - deleteThis("ConnStateData::connStateClosed"); -} - #if USE_AUTH void ConnStateData::setAuth(const Auth::UserRequest::Pointer &aur, const char *by) { if (auth_ == NULL) { if (aur != NULL) { - debugs(33, 2, "Adding connection-auth to " << clientConnection << " from " << by); + debugs(33, 2, "Adding connection-auth to " << tcp << " from " << by); auth_ = aur; } return; @@ -790,7 +763,7 @@ // clobered with self-pointer // NP: something nasty is going on in Squid, but harmless. if (aur == auth_) { - debugs(33, 2, "WARNING: Ignoring duplicate connection-auth for " << clientConnection << " from " << by); + debugs(33, 2, "WARNING: Ignoring duplicate connection-auth for " << tcp << " from " << by); return; } @@ -831,7 +804,7 @@ // clobbered with nul-pointer if (aur == NULL) { - debugs(33, 2, "WARNING: Graceful closure on " << clientConnection << " due to connection-auth erase from " << by); + debugs(33, 2, "WARNING: Graceful closure on " << tcp << " due to connection-auth erase from " << by); auth_->releaseAuthServer(); auth_ = NULL; // XXX: need to test whether the connection re-auth challenge is sent. If not, how to trigger it from here. @@ -843,12 +816,12 @@ // clobbered with alternative credentials if (aur != auth_) { - debugs(33, 2, "ERROR: Closing " << clientConnection << " due to change of connection-auth from " << by); + debugs(33, 2, "ERROR: Closing " << tcp << " due to change of connection-auth from " << by); auth_->releaseAuthServer(); auth_ = NULL; // this is a fatal type of problem. // Close the connection immediately with TCP RST to abort all traffic flow - comm_reset_close(clientConnection); + comm_reset_close(tcp); return; } @@ -860,19 +833,17 @@ void ConnStateData::swanSong() { - debugs(33, 2, HERE << clientConnection); + debugs(33, 2, tcp); flags.readMore = false; - clientdbEstablished(clientConnection->remote, -1); /* decrement */ + clientdbEstablished(tcp->remote, -1); /* decrement */ assert(areAllContextsForThisConnection()); freeAllContexts(); unpinConnection(); - - if (Comm::IsConnOpen(clientConnection)) - clientConnection->close(); + Comm::TcpReceiver::swanSong(); #if USE_AUTH - // NP: do this bit after closing the connections to avoid side effects from unwanted TCP RST + // NP: do this bit after TcpReceiver::swanSong (TCP connection cleanup) to avoid side effects from unwanted TCP RST setAuth(NULL, "ConnStateData::SwanSong cleanup"); #endif @@ -884,20 +855,20 @@ ConnStateData::isOpen() const { return cbdataReferenceValid(this) && // XXX: checking "this" in a method - Comm::IsConnOpen(clientConnection) && - !fd_table[clientConnection->fd].closing(); + Comm::IsConnOpen(tcp) && + !fd_table[tcp->fd].closing(); } ConnStateData::~ConnStateData() { assert(this != NULL); - debugs(33, 3, HERE << clientConnection); + debugs(33, 3, tcp); if (isOpen()) - debugs(33, DBG_IMPORTANT, "BUG: ConnStateData did not close " << clientConnection); + debugs(33, DBG_IMPORTANT, "BUG: ConnStateData did not close " << tcp); if (!flags.swanSang) - debugs(33, DBG_IMPORTANT, "BUG: ConnStateData was not destroyed properly; " << clientConnection); + debugs(33, DBG_IMPORTANT, "BUG: ConnStateData was not destroyed properly; " << tcp); cbdataReferenceDone(port); @@ -962,7 +933,7 @@ bool connIsUsable(ConnStateData * conn) { - if (conn == NULL || !cbdataReferenceValid(conn) || !Comm::IsConnOpen(conn->clientConnection)) + if (conn == NULL || !cbdataReferenceValid(conn) || !Comm::IsConnOpen(conn->tcp)) return false; return true; @@ -1581,16 +1552,16 @@ void ConnStateData::readNextRequest() { - debugs(33, 5, HERE << clientConnection << " reading next req"); + debugs(33, 5, tcp << " reading next req"); - fd_note(clientConnection->fd, "Idle client: Waiting for next request"); + fd_note(tcp->fd, "Idle client: Waiting for next request"); /** - * Set the timeout BEFORE calling clientReadRequest(). + * Set the timeout BEFORE calling readSomeData(). */ typedef CommCbMemFunT TimeoutDialer; AsyncCall::Pointer timeoutCall = JobCallback(33, 5, TimeoutDialer, this, ConnStateData::requestTimeout); - commSetConnTimeout(clientConnection, Config.Timeout.clientIdlePconn, timeoutCall); + commSetConnTimeout(tcp, Config.Timeout.clientIdlePconn, timeoutCall); readSomeData(); /** Please don't do anything with the FD past here! */ @@ -1599,7 +1570,7 @@ static void ClientSocketContextPushDeferredIfNeeded(ClientSocketContext::Pointer deferredRequest, ConnStateData * conn) { - debugs(33, 2, HERE << conn->clientConnection << " Sending next"); + debugs(33, 2, conn->tcp << " Sending next"); /** If the client stream is waiting on a socket write to occur, then */ @@ -1624,12 +1595,12 @@ { ConnStateData * conn = http->getConn(); - debugs(33, 3, HERE << "ConnnStateData(" << conn->clientConnection << "), Context(" << clientConnection << ")"); + debugs(33, 3, "ConnnStateData(" << conn->tcp << "), Context(" << clientConnection << ")"); connIsFinished(); if (conn->pinning.pinned && !Comm::IsConnOpen(conn->pinning.serverConnection)) { - debugs(33, 2, HERE << conn->clientConnection << " Connection was pinned but server side gone. Terminating client connection"); - conn->clientConnection->close(); + debugs(33, 2, conn->tcp << " Connection was pinned but server side gone. Terminating client connection"); + conn->tcp->close(); return; } @@ -1648,8 +1619,8 @@ */ if (const char *reason = conn->stoppedReceiving()) { - debugs(33, 3, HERE << "closing for earlier request error: " << reason); - conn->clientConnection->close(); + debugs(33, 3, "closing for earlier request error: " << reason); + conn->tcp->close(); return; } @@ -1664,7 +1635,7 @@ */ if (conn->clientParseRequests()) { - debugs(33, 3, HERE << conn->clientConnection << ": parsed next request from buffer"); + debugs(33, 3, conn->tcp << ": parsed next request from buffer"); } /** \par @@ -1674,9 +1645,9 @@ * half-closed _AND_ then, sometimes, spending "Timeout" time in * the keepalive "Waiting for next request" state. */ - if (commIsHalfClosed(conn->clientConnection->fd) && (conn->getConcurrentRequestCount() == 0)) { - debugs(33, 3, "ClientSocketContext::keepaliveNextRequest: half-closed client with no pending requests, closing"); - conn->clientConnection->close(); + if (commIsHalfClosed(conn->tcp->fd) && (conn->getConcurrentRequestCount() == 0)) { + debugs(33, 3, "half-closed client with no pending requests, closing"); + conn->tcp->close(); return; } @@ -1691,14 +1662,14 @@ */ if ((deferredRequest = conn->getCurrentContext()).getRaw()) { - debugs(33, 3, HERE << conn->clientConnection << ": calling PushDeferredIfNeeded"); + debugs(33, 3, conn->tcp << ": calling PushDeferredIfNeeded"); ClientSocketContextPushDeferredIfNeeded(deferredRequest, conn); } else if (conn->flags.readMore) { - debugs(33, 3, HERE << conn->clientConnection << ": calling conn->readNextRequest()"); + debugs(33, 3, conn->tcp << ": calling conn->readNextRequest()"); conn->readNextRequest(); } else { // XXX: Can this happen? CONNECT tunnels have deferredRequest set. - debugs(33, DBG_IMPORTANT, HERE << "abandoning " << conn->clientConnection); + debugs(33, DBG_IMPORTANT, HERE << "abandoning " << conn->tcp); } } @@ -1904,30 +1875,6 @@ } void -ConnStateData::stopSending(const char *error) -{ - debugs(33, 4, HERE << "sending error (" << clientConnection << "): " << error << - "; old receiving error: " << - (stoppedReceiving() ? stoppedReceiving_ : "none")); - - if (const char *oldError = stoppedSending()) { - debugs(33, 3, HERE << "already stopped sending: " << oldError); - return; // nothing has changed as far as this connection is concerned - } - stoppedSending_ = error; - - if (!stoppedReceiving()) { - if (const int64_t expecting = mayNeedToReadMoreBody()) { - debugs(33, 5, HERE << "must still read " << expecting << - " request body bytes with " << in.notYetUsed << " unused"); - return; // wait for the request receiver to finish reading - } - } - - clientConnection->close(); -} - -void ClientSocketContext::writeComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag) { const StoreEntry *entry = http->storeEntry(); @@ -1983,10 +1930,10 @@ ClientSocketContext *context; StoreIOBuffer tempBuffer; http = new ClientHttpRequest(csd); - http->req_sz = csd->in.notYetUsed; + http->req_sz = csd->inBuf.contentSize(); http->uri = xstrdup(uri); setLogUri (http, uri); - context = ClientSocketContextNew(csd->clientConnection, http); + context = ClientSocketContextNew(csd->tcp, http); tempBuffer.data = context->reqbuf; tempBuffer.length = HTTP_REQBUF_SZ; clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach, @@ -2123,7 +2070,7 @@ } if (vport < 0) - vport = http->getConn()->clientConnection->local.port(); + vport = http->getConn()->tcp->local.port(); const bool switchedToHttps = conn->switchedToHttps(); const bool tryHostHeader = vhost || switchedToHttps; @@ -2167,7 +2114,7 @@ /* Put the local socket IP address as the hostname, with whatever vport we found */ int url_sz = strlen(url) + 32 + Config.appendDomainLen; http->uri = (char *)xcalloc(url_sz, 1); - http->getConn()->clientConnection->local.toHostStr(ipbuf,MAX_IPSTRLEN); + http->getConn()->tcp->local.toHostStr(ipbuf,MAX_IPSTRLEN); snprintf(http->uri, url_sz, "%s://%s:%d%s", URLScheme(conn->port->transport.protocol).const_str(), ipbuf, vport, url); @@ -2196,10 +2143,10 @@ /* Put the local socket IP address as the hostname. */ int url_sz = strlen(url) + 32 + Config.appendDomainLen; http->uri = (char *)xcalloc(url_sz, 1); - http->getConn()->clientConnection->local.toHostStr(ipbuf,MAX_IPSTRLEN); + http->getConn()->tcp->local.toHostStr(ipbuf,MAX_IPSTRLEN); snprintf(http->uri, url_sz, "%s://%s:%d%s", URLScheme(http->getConn()->port->transport.protocol).const_str(), - ipbuf, http->getConn()->clientConnection->local.port(), url); + ipbuf, http->getConn()->tcp->local.port(), url); debugs(33, 5, "TRANSPARENT REWRITE: '" << http->uri << "'"); } } @@ -2327,7 +2274,7 @@ http = new ClientHttpRequest(csd); http->req_sz = HttpParserRequestLen(hp); - result = ClientSocketContextNew(csd->clientConnection, http); + result = ClientSocketContextNew(csd->tcp, http); tempBuffer.data = result->reqbuf; tempBuffer.length = HTTP_REQBUF_SZ; @@ -2398,7 +2345,7 @@ debugs(33, 5, "parseHttpRequest: Complete request received"); // XXX: crop this dump at the end of headers. No need for extras - debugs(11, 2, "HTTP Client " << csd->clientConnection); + debugs(11, 2, "HTTP Client " << csd->tcp); debugs(11, 2, "HTTP Client REQUEST:\n---------\n" << (hp->buf) + hp->req.m_start << "\n----------"); result->flags.parsed_ok = 1; @@ -2406,34 +2353,6 @@ return result; } -int -ConnStateData::getAvailableBufferLength() const -{ - assert (in.allocatedSize > in.notYetUsed); // allocated more than used - const size_t result = in.allocatedSize - in.notYetUsed - 1; - // huge request_header_max_size may lead to more than INT_MAX unused space - assert (static_cast(result) <= INT_MAX); - return result; -} - -bool -ConnStateData::maybeMakeSpaceAvailable() -{ - if (getAvailableBufferLength() < 2) { - size_t newSize; - if (in.allocatedSize >= Config.maxRequestBufferSize) { - debugs(33, 4, "request buffer full: client_request_buffer_max_size=" << Config.maxRequestBufferSize); - return false; - } - if ((newSize=in.allocatedSize * 2) > Config.maxRequestBufferSize) { - newSize=Config.maxRequestBufferSize; - } - in.buf = (char *)memReallocBuf(in.buf, newSize, &in.allocatedSize); - debugs(33, 2, "growing request buffer: notYetUsed=" << in.notYetUsed << " size=" << in.allocatedSize); - } - return true; -} - void ConnStateData::addContextToQueue(ClientSocketContext * context) { @@ -2457,68 +2376,31 @@ return result; } -int -ConnStateData::connReadWasError(comm_err_t flag, int size, int xerrno) -{ - if (flag != COMM_OK) { - debugs(33, 2, "connReadWasError: FD " << clientConnection << ": got flag " << flag); - return 1; - } - - if (size < 0) { - if (!ignoreErrno(xerrno)) { - debugs(33, 2, "connReadWasError: FD " << clientConnection << ": " << xstrerr(xerrno)); - return 1; - } else if (in.notYetUsed == 0) { - debugs(33, 2, "connReadWasError: FD " << clientConnection << ": no data to process (" << xstrerr(xerrno) << ")"); - } - } - - return 0; -} - -int -ConnStateData::connFinishedWithConn(int size) -{ - if (size == 0) { - if (getConcurrentRequestCount() == 0 && in.notYetUsed == 0) { - /* no current or pending requests */ - debugs(33, 4, HERE << clientConnection << " closed"); - return 1; - } else if (!Config.onoff.half_closed_clients) { - /* admin doesn't want to support half-closed client sockets */ - debugs(33, 3, HERE << clientConnection << " aborted (half_closed_clients disabled)"); - notifyAllContexts(0); // no specific error implies abort - return 1; - } - } - - return 0; -} - -void -connNoteUseOfBuffer(ConnStateData* conn, size_t byteCount) -{ - assert(byteCount > 0 && byteCount <= conn->in.notYetUsed); - conn->in.notYetUsed -= byteCount; - debugs(33, 5, HERE << "conn->in.notYetUsed = " << conn->in.notYetUsed); - /* - * If there is still data that will be used, - * move it to the beginning. - */ - - if (conn->in.notYetUsed > 0) - memmove(conn->in.buf, conn->in.buf + byteCount, conn->in.notYetUsed); +const char * +ConnStateData::maybeFinishedWithTcp() +{ + if (getConcurrentRequestCount() == 0 && !inBuf.hasContent()) { + /* no current or pending requests */ + debugs(33, 4, tcp << " closed"); + return "done"; + } else if (!Config.onoff.half_closed_clients) { + /* admin doesn't want to support half-closed client sockets */ + debugs(33, 3, tcp << " aborted (half_closed_clients disabled)"); + noteTcpReadError(0); // no specific error implies abort + return "half_closed_clients disabled"; + } + + return NULL; } /// respond with ERR_TOO_BIG if request header exceeds request_header_max_size void ConnStateData::checkHeaderLimits() { - if (in.notYetUsed < Config.maxRequestHeaderSize) + if (inBuf.contentSize() < static_cast(Config.maxRequestHeaderSize)) return; // can accumulte more header data - debugs(33, 3, "Request header is too large (" << in.notYetUsed << " > " << + debugs(33, 3, "Request header is too large (" << inBuf.contentSize() << " > " << Config.maxRequestHeaderSize << " bytes)"); ClientSocketContext *context = parseHttpRequestAbort(this, "error:request-too-large"); @@ -2527,26 +2409,12 @@ assert (repContext); repContext->setReplyToError(ERR_TOO_BIG, Http::scBadRequest, Http::METHOD_NONE, NULL, - clientConnection->remote, NULL, NULL, NULL); + tcp->remote, NULL, NULL, NULL); context->registerWithConn(); context->pullData(); } void -ConnStateData::clientAfterReadingRequests() -{ - // Were we expecting to read more request body from half-closed connection? - if (mayNeedToReadMoreBody() && commIsHalfClosed(clientConnection->fd)) { - debugs(33, 3, HERE << "truncated body: closing half-closed " << clientConnection); - clientConnection->close(); - return; - } - - if (flags.readMore) - readSomeData(); -} - -void ConnStateData::quitAfterError(HttpRequest *request) { // From HTTP p.o.v., we do not have to close after every error detected @@ -2555,7 +2423,7 @@ if (request) request->flags.proxyKeepalive = false; flags.readMore = false; - debugs(33,4, HERE << "Will close after error: " << clientConnection); + debugs(33,4, "Will close after error: " << tcp); } #if USE_SSL @@ -2649,7 +2517,7 @@ { ClientHttpRequest *http = context->http; HttpRequest::Pointer request; - bool notedUseOfBuffer = false; + bool reqConsumedFromBuffer = false; bool chunked = false; bool mustReplyToOptions = false; bool unsupportedTe = false; @@ -2669,15 +2537,15 @@ assert (repContext); switch (hp->request_parse_status) { case Http::scHeaderTooLarge: - repContext->setReplyToError(ERR_TOO_BIG, Http::scBadRequest, method, http->uri, conn->clientConnection->remote, NULL, conn->in.buf, NULL); + repContext->setReplyToError(ERR_TOO_BIG, Http::scBadRequest, method, http->uri, conn->tcp->remote, NULL, conn->inBuf.content(), NULL); break; case Http::scMethodNotAllowed: repContext->setReplyToError(ERR_UNSUP_REQ, Http::scMethodNotAllowed, method, http->uri, - conn->clientConnection->remote, NULL, conn->in.buf, NULL); + conn->tcp->remote, NULL, conn->inBuf.content(), NULL); break; default: repContext->setReplyToError(ERR_INVALID_REQ, hp->request_parse_status, method, http->uri, - conn->clientConnection->remote, NULL, conn->in.buf, NULL); + conn->tcp->remote, NULL, conn->inBuf.content(), NULL); } assert(context->http->out.offset == 0); context->pullData(); @@ -2692,7 +2560,7 @@ setLogUri(http, http->uri, true); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); - repContext->setReplyToError(ERR_INVALID_URL, Http::scBadRequest, method, http->uri, conn->clientConnection->remote, NULL, NULL, NULL); + repContext->setReplyToError(ERR_INVALID_URL, Http::scBadRequest, method, http->uri, conn->tcp->remote, NULL, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); goto finish; @@ -2711,7 +2579,7 @@ clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); repContext->setReplyToError(ERR_UNSUP_HTTPVERSION, Http::scHttpVersionNotSupported, method, http->uri, - conn->clientConnection->remote, NULL, HttpParserHdrBuf(hp), NULL); + conn->tcp->remote, NULL, HttpParserHdrBuf(hp), NULL); assert(context->http->out.offset == 0); context->pullData(); goto finish; @@ -2728,7 +2596,7 @@ setLogUri(http, http->uri, true); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); - repContext->setReplyToError(ERR_INVALID_REQ, Http::scBadRequest, method, http->uri, conn->clientConnection->remote, NULL, NULL, NULL); + repContext->setReplyToError(ERR_INVALID_REQ, Http::scBadRequest, method, http->uri, conn->tcp->remote, NULL, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); goto finish; @@ -2785,13 +2653,13 @@ request->flags.internal = http->flags.internal; setLogUri (http, urlCanonicalClean(request.getRaw())); - request->client_addr = conn->clientConnection->remote; // XXX: remove reuest->client_addr member. + request->client_addr = conn->tcp->remote; // XXX: remove reuest->client_addr member. #if FOLLOW_X_FORWARDED_FOR // indirect client gets stored here because it is an HTTP header result (from X-Forwarded-For:) // not a details about teh TCP connection itself - request->indirect_client_addr = conn->clientConnection->remote; + request->indirect_client_addr = conn->tcp->remote; #endif /* FOLLOW_X_FORWARDED_FOR */ - request->my_addr = conn->clientConnection->local; + request->my_addr = conn->tcp->local; request->myportname = conn->port->name; request->http_ver = http_ver; @@ -2815,7 +2683,7 @@ clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); repContext->setReplyToError(ERR_UNSUP_REQ, Http::scNotImplemented, request->method, NULL, - conn->clientConnection->remote, request.getRaw(), NULL, NULL); + conn->tcp->remote, request.getRaw(), NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); goto finish; @@ -2828,7 +2696,7 @@ conn->quitAfterError(request.getRaw()); repContext->setReplyToError(ERR_INVALID_REQ, Http::scLengthRequired, request->method, NULL, - conn->clientConnection->remote, request.getRaw(), NULL, NULL); + conn->tcp->remote, request.getRaw(), NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); goto finish; @@ -2843,7 +2711,7 @@ assert (repContext); conn->quitAfterError(request.getRaw()); repContext->setReplyToError(ERR_INVALID_REQ, Http::scExpectationFailed, request->method, http->uri, - conn->clientConnection->remote, request.getRaw(), NULL, NULL); + conn->tcp->remote, request.getRaw(), NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); goto finish; @@ -2872,8 +2740,8 @@ chunked ? -1 : request->content_length); // consume header early so that body pipe gets just the body - connNoteUseOfBuffer(conn, http->req_sz); - notedUseOfBuffer = true; + conn->inBuf.consume(http->req_sz); + reqConsumedFromBuffer = true; /* Is it too large? */ if (!chunked && // if chunked, we will check as we accumulate @@ -2884,7 +2752,7 @@ conn->quitAfterError(request.getRaw()); repContext->setReplyToError(ERR_TOO_BIG, Http::scRequestEntityTooLarge, Http::METHOD_NONE, NULL, - conn->clientConnection->remote, http->request, NULL, NULL); + conn->tcp->remote, http->request, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); goto finish; @@ -2892,7 +2760,7 @@ // We may stop producing, comm_close, and/or call setReplyToError() // below, so quit on errors to avoid http->doCallouts() - if (!conn->handleRequestBodyData()) + if (!conn->processRequestBodyData(conn->inBuf)) goto finish; if (!request->body_pipe->productionEnded()) { @@ -2907,29 +2775,13 @@ http->doCallouts(); finish: - if (!notedUseOfBuffer) - connNoteUseOfBuffer(conn, http->req_sz); + if (!reqConsumedFromBuffer) + conn->inBuf.consume(http->req_sz); - /* - * DPW 2007-05-18 - * Moved the TCP_RESET feature from clientReplyContext::sendMoreData - * to here because calling comm_reset_close() causes http to - * be freed and the above connNoteUseOfBuffer() would hit an - * assertion, not to mention that we were accessing freed memory. - */ - if (request != NULL && request->flags.resetTcp && Comm::IsConnOpen(conn->clientConnection)) { - debugs(33, 3, HERE << "Sending TCP RST on " << conn->clientConnection); + if (request != NULL && request->flags.resetTcp && Comm::IsConnOpen(conn->tcp)) { + debugs(33, 3, "Sending TCP RST on " << conn->tcp); conn->flags.readMore = false; - comm_reset_close(conn->clientConnection); - } -} - -static void -connStripBufferWhitespace (ConnStateData * conn) -{ - while (conn->in.notYetUsed > 0 && xisspace(conn->in.buf[0])) { - memmove(conn->in.buf, conn->in.buf + 1, conn->in.notYetUsed - 1); - -- conn->in.notYetUsed; + comm_reset_close(conn->tcp); // may free 'http' } } @@ -2949,8 +2801,8 @@ // when queue filled already we cant add more. if (existingRequestCount >= concurrentRequestLimit) { - debugs(33, 3, clientConnection << " max concurrent requests reached (" << concurrentRequestLimit << ")"); - debugs(33, 5, clientConnection << " deferring new request until one is done"); + debugs(33, 3, tcp << " max concurrent requests reached (" << concurrentRequestLimit << ")"); + debugs(33, 5, tcp << " deferring new request until one is done"); return true; } @@ -2968,28 +2820,24 @@ HttpRequestMethod method; bool parsed_req = false; - debugs(33, 5, HERE << clientConnection << ": attempting to parse"); + debugs(33, 5, tcp << ": attempting to parse ..."); // Loop while we have read bytes that are not needed for producing the body // On errors, bodyPipe may become nil, but readMore will be cleared - while (in.notYetUsed > 0 && !bodyPipe && flags.readMore) { - connStripBufferWhitespace(this); + while (inBuf.hasContent() && !bodyPipe && flags.readMore) { + inBuf.consumeWhitespacePrefix(); /* Don't try to parse if the buffer is empty */ - if (in.notYetUsed == 0) + if (!inBuf.hasContent()) break; /* Limit the number of concurrent requests */ if (concurrentRequestQueueFilled()) break; - /* Should not be needed anymore */ - /* Terminate the string */ - in.buf[in.notYetUsed] = '\0'; - /* Begin the parsing */ PROF_start(parseHttpRequest); - HttpParserInit(&parser_, in.buf, in.notYetUsed); + HttpParserInit(&parser_, inBuf.content(), inBuf.contentSize()); // XXX: pass MemBuf & /* Process request */ Http::ProtocolVersion http_ver; @@ -3006,10 +2854,10 @@ /* status -1 or 1 */ if (context) { - debugs(33, 5, HERE << clientConnection << ": parsed a request"); + debugs(33, 5, tcp << ": parsed a request"); AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "clientLifetimeTimeout", CommTimeoutCbPtrFun(clientLifetimeTimeout, context->http)); - commSetConnTimeout(clientConnection, Config.Timeout.lifetime, timeoutCall); + commSetConnTimeout(tcp, Config.Timeout.lifetime, timeoutCall); clientProcessRequest(this, &parser_, context, method, http_ver); @@ -3026,141 +2874,68 @@ return parsed_req; } -void -ConnStateData::clientReadRequest(const CommIoCbParams &io) +/** + * called when new request message data has been buffered in inBuf + * may close the connection if we were closing and piped everything out + * + * \return false when read() needs to be abandoned + */ +bool +ConnStateData::processRequestMessageData(MemBuf &aBuf) { - debugs(33,5,HERE << io.conn << " size " << io.size); - Must(reading()); - reader = NULL; - - /* Bail out quickly on COMM_ERR_CLOSING - close handlers will tidy up */ - - if (io.flag == COMM_ERR_CLOSING) { - debugs(33,5, HERE << io.conn << " closing Bailout."); - return; - } - - assert(Comm::IsConnOpen(clientConnection)); - assert(io.conn->fd == clientConnection->fd); - - /* - * Don't reset the timeout value here. The timeout value will be - * set to Config.Timeout.request by httpAccept() and - * clientWriteComplete(), and should apply to the request as a - * whole, not individual read() calls. Plus, it breaks our - * lame half-close detection - */ - if (connReadWasError(io.flag, io.size, io.xerrno)) { - notifyAllContexts(io.xerrno); - io.conn->close(); - return; - } - - if (io.flag == COMM_OK) { - if (io.size > 0) { - kb_incr(&(statCounter.client_http.kbytes_in), io.size); - - // may comm_close or setReplyToError - if (!handleReadData(io.buf, io.size)) - return; - - } else if (io.size == 0) { - debugs(33, 5, HERE << io.conn << " closed?"); - - if (connFinishedWithConn(io.size)) { - clientConnection->close(); - return; - } - - /* It might be half-closed, we can't tell */ - fd_table[io.conn->fd].flags.socket_eof = true; - - commMarkHalfClosed(io.conn->fd); - - fd_note(io.conn->fd, "half-closed"); - - /* There is one more close check at the end, to detect aborted - * (partial) requests. At this point we can't tell if the request - * is partial. - */ - /* Continue to process previously read data */ - } - } - /* Process next request */ - if (getConcurrentRequestCount() == 0) - fd_note(io.fd, "Reading next request"); + fd_note(tcp->fd, "Reading next request"); if (!clientParseRequests()) { - if (!isOpen()) - return; - /* - * If the client here is half closed and we failed - * to parse a request, close the connection. - * The above check with connFinishedWithConn() only - * succeeds _if_ the buffer is empty which it won't - * be if we have an incomplete request. - * XXX: This duplicates ClientSocketContext::keepaliveNextRequest - */ - if (getConcurrentRequestCount() == 0 && commIsHalfClosed(io.fd)) { - debugs(33, 5, HERE << io.conn << ": half-closed connection, no completed request parsed, connection closing."); - clientConnection->close(); - return; + if (stoppedReceiving() && getConcurrentRequestCount() == 0) { + // all outstanding requests done. no more requests able to come in. + debugs(33, 5, tcp << ": half-closed connection, no completed request parsed, connection closing."); + stopSending("no more requests to happen. Abandon incomplete request."); + return false; } } + // XXX: should not be needed anymore if (!isOpen()) - return; + return false; - clientAfterReadingRequests(); + // when readMore is false we abort reading, even if the socket is good + return flags.readMore; } -/** - * called when new request data has been read from the socket - * - * \retval false called comm_close or setReplyToError (the caller should bail) - * \retval true we did not call comm_close or setReplyToError - */ bool -ConnStateData::handleReadData(char *buf, size_t size) +ConnStateData::processReadBuffer(MemBuf &aBuf) { - char *current_buf = in.addressToReadInto(); - - if (buf != current_buf) - memmove(current_buf, buf, size); - - in.notYetUsed += size; - - in.buf[in.notYetUsed] = '\0'; /* Terminate the string */ - // if we are reading a body, stuff data into the body pipe if (bodyPipe != NULL) - return handleRequestBodyData(); - return true; + return processRequestBodyData(aBuf); + + // if we are expecting a message frame, try to parse + return processRequestMessageData(aBuf); } /** - * called when new request body data has been buffered in in.buf + * called when new request body data has been buffered in inBuf * may close the connection if we were closing and piped everything out * * \retval false called comm_close or setReplyToError (the caller should bail) * \retval true we did not call comm_close or setReplyToError */ bool -ConnStateData::handleRequestBodyData() +ConnStateData::processRequestBodyData(MemBuf &aBuf) { assert(bodyPipe != NULL); size_t putSize = 0; - if (in.bodyParser) { // chunked encoding + if (bodyParser_) { // chunked encoding if (const err_type error = handleChunkedRequestBody(putSize)) { abortChunkedRequestBody(error); return false; } } else { // identity encoding - debugs(33,5, HERE << "handling plain request body for " << clientConnection); - putSize = bodyPipe->putMoreData(in.buf, in.notYetUsed); + debugs(33,5, "handling plain request body for " << tcp); + putSize = bodyPipe->putMoreData(aBuf.content(), aBuf.contentSize()); if (!bodyPipe->mayNeedMoreData()) { // BodyPipe will clear us automagically when we produced everything bodyPipe = NULL; @@ -3168,17 +2943,17 @@ } if (putSize > 0) - connNoteUseOfBuffer(this, putSize); + aBuf.consume(putSize); if (!bodyPipe) { - debugs(33,5, HERE << "produced entire request body for " << clientConnection); + debugs(33,5, "produced entire request body for " << tcp); if (const char *reason = stoppedSending()) { /* we've finished reading like good clients, * now do the close that initiateClose initiated. */ debugs(33, 3, HERE << "closing for earlier sending error: " << reason); - clientConnection->close(); + tcp->close(); return false; } } @@ -3190,23 +2965,18 @@ err_type ConnStateData::handleChunkedRequestBody(size_t &putSize) { - debugs(33,7, HERE << "chunked from " << clientConnection << ": " << in.notYetUsed); + debugs(33,7, "chunked from " << tcp << ": " << inBuf.contentSize()); try { // the parser will throw on errors - if (!in.notYetUsed) // nothing to do (MemBuf::init requires this check) + if (!inBuf.hasContent()) return ERR_NONE; - MemBuf raw; // ChunkedCodingParser only works with MemBufs - // add one because MemBuf will assert if it cannot 0-terminate - raw.init(in.notYetUsed, in.notYetUsed+1); - raw.append(in.buf, in.notYetUsed); - - const mb_size_t wasContentSize = raw.contentSize(); + const mb_size_t wasContentSize = inBuf.contentSize(); BodyPipeCheckout bpc(*bodyPipe); - const bool parsed = in.bodyParser->parse(&raw, &bpc.buf); + const bool parsed = bodyParser_->parse(&inBuf, &bpc.buf); bpc.checkIn(); - putSize = wasContentSize - raw.contentSize(); + putSize = wasContentSize - inBuf.contentSize(); // dechunk then check: the size limit applies to _dechunked_ content if (clientIsRequestBodyTooLargeForPolicy(bodyPipe->producedSize())) @@ -3219,10 +2989,10 @@ } // if chunk parser needs data, then the body pipe must need it too - Must(!in.bodyParser->needsMoreData() || bodyPipe->mayNeedMoreData()); + Must(!bodyParser_->needsMoreData() || bodyPipe->mayNeedMoreData()); // if parser needs more space and we can consume nothing, we will stall - Must(!in.bodyParser->needsMoreSpace() || bodyPipe->buf().hasContent()); + Must(!bodyParser_->needsMoreSpace() || bodyPipe->buf().hasContent()); } catch (...) { // TODO: be more specific debugs(33, 3, HERE << "malformed chunks" << bodyPipe->status()); return ERR_INVALID_REQ; @@ -3254,15 +3024,15 @@ repContext->http->uri, CachePeer, repContext->http->request, - in.buf, NULL); + inBuf.content(), NULL); context->pullData(); } else { // close or otherwise we may get stuck as nobody will notice the error? - comm_reset_close(clientConnection); + comm_reset_close(tcp); } #else debugs(33, 3, HERE << "aborting chunked request without error " << error); - comm_reset_close(clientConnection); + comm_reset_close(tcp); #endif flags.readMore = false; } @@ -3270,14 +3040,8 @@ void ConnStateData::noteMoreBodySpaceAvailable(BodyPipe::Pointer ) { - if (!handleRequestBodyData()) - return; - - // too late to read more body - if (!isOpen() || stoppedReceiving()) - return; - - readSomeData(); + if (processReadBuffer(inBuf)) + readSomeData(); } void @@ -3319,13 +3083,13 @@ ConnStateData::ConnStateData(const MasterXaction::Pointer &xact) : AsyncJob("ConnStateData"), + Comm::TcpReceiver(xact->tcpClient), #if USE_SSL sslBumpMode(Ssl::bumpEnd), switchedToHttps_(false), sslServerBump(NULL), #endif - stoppedSending_(NULL), - stoppedReceiving_(NULL) + bodyParser_(NULL) { pinning.host = NULL; pinning.port = -1; @@ -3335,19 +3099,20 @@ pinning.peer = NULL; // store the details required for creating more MasterXaction objects as new requests come in - clientConnection = xact->tcpClient; port = cbdataReference(xact->squidPort.get()); log_addr = xact->tcpClient->remote; log_addr.applyMask(Config.Addrs.client_netmask); - in.buf = (char *)memAllocBuf(CLIENT_REQ_BUF_SZ, &in.allocatedSize); + tcpConnectionInit(); + inBuf.init(CLIENT_REQ_BUF_SZ, Config.maxRequestBufferSize); + debugs(33, 8, "inBuf space=" << inBuf.spaceSize()); if (port->disable_pmtu_discovery != DISABLE_PMTU_OFF && (transparent() || port->disable_pmtu_discovery == DISABLE_PMTU_ALWAYS)) { #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) int i = IP_PMTUDISC_DONT; - if (setsockopt(clientConnection->fd, SOL_IP, IP_MTU_DISCOVER, &i, sizeof(i)) < 0) - debugs(33, 2, "WARNING: Path MTU discovery disabling failed on " << clientConnection << " : " << xstrerror()); + if (setsockopt(tcp->fd, SOL_IP, IP_MTU_DISCOVER, &i, sizeof(i)) < 0) + debugs(33, 2, "WARNING: Path MTU discovery disabling failed on " << tcp << " : " << xstrerror()); #else static bool reported = false; @@ -3358,12 +3123,8 @@ #endif } - typedef CommCbMemFunT Dialer; - AsyncCall::Pointer call = JobCallback(33, 5, Dialer, this, ConnStateData::connStateClosed); - comm_add_close_handler(clientConnection->fd, call); - if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(clientConnection->remote, FQDN_LOOKUP_IF_MISS); + fqdncache_gethostbyaddr(tcp->remote, FQDN_LOOKUP_IF_MISS); #if USE_IDENT if (Ident::TheConfig.identLookup) { @@ -3375,7 +3136,7 @@ } #endif - clientdbEstablished(clientConnection->remote, 1); + clientdbEstablished(tcp->remote, 1); flags.readMore = true; } @@ -3616,7 +3377,7 @@ { SSL *ssl = NULL; assert(connState); - const Comm::ConnectionPointer &details = connState->clientConnection; + const Comm::ConnectionPointer &details = connState->tcp; if (sslContext && !(ssl = httpsCreate(details, sslContext))) return; @@ -3635,13 +3396,13 @@ fakeRequest->SetHost(details->local.toStr(buf, sizeof(buf))); fakeRequest->port = details->local.port(); fakeRequest->clientConnectionManager = connState; - fakeRequest->client_addr = connState->clientConnection->remote; + fakeRequest->client_addr = connState->tcp->remote; #if FOLLOW_X_FORWARDED_FOR - fakeRequest->indirect_client_addr = connState->clientConnection->remote; + fakeRequest->indirect_client_addr = connState->tcp->remote; #endif - fakeRequest->my_addr = connState->clientConnection->local; - fakeRequest->flags.interceptTproxy = ((connState->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ; - fakeRequest->flags.intercepted = ((connState->clientConnection->flags & COMM_INTERCEPTION) != 0); + fakeRequest->my_addr = connState->tcp->local; + fakeRequest->flags.interceptTproxy = ((connState->tcp->flags & COMM_TRANSPARENT) != 0 ) ; + fakeRequest->flags.intercepted = ((connState->tcp->flags & COMM_INTERCEPTION) != 0); fakeRequest->myportname = connState->port->name; if (fakeRequest->flags.interceptTproxy) { if (Config.accessList.spoof_client_ip) { @@ -3673,25 +3434,20 @@ // Require both a match and a positive bump mode to work around exceptional // cases where ACL code may return ACCESS_ALLOWED with zero answer.kind. if (answer == ACCESS_ALLOWED && answer.kind != Ssl::bumpNone) { - debugs(33, 2, HERE << "sslBump needed for " << connState->clientConnection); + debugs(33, 2, "sslBump needed for " << connState->tcp); connState->sslBumpMode = static_cast(answer.kind); httpsEstablish(connState, NULL, (Ssl::BumpMode)answer.kind); } else { - debugs(33, 2, HERE << "sslBump not needed for " << connState->clientConnection); + debugs(33, 2, "sslBump not needed for " << connState->tcp); connState->sslBumpMode = Ssl::bumpNone; // fake a CONNECT request to force connState to tunnel static char ip[MAX_IPSTRLEN]; - static char reqStr[MAX_IPSTRLEN + 80]; - connState->clientConnection->local.toUrl(ip, sizeof(ip)); - snprintf(reqStr, sizeof(reqStr), "CONNECT %s HTTP/1.1\r\nHost: %s\r\n\r\n", ip, ip); - bool ret = connState->handleReadData(reqStr, strlen(reqStr)); - if (ret) - ret = connState->clientParseRequests(); - - if (!ret) { - debugs(33, 2, HERE << "Failed to start fake CONNECT request for ssl bumped connection: " << connState->clientConnection); - connState->clientConnection->close(); + connState->tcp->local.toUrl(ip, sizeof(ip)); + connState->inBuf.Printf("CONNECT %s HTTP/1.1\r\nHost: %s\r\n\r\n", ip, ip); + if (!connState->processReadBuffer(inBuf)) { + debugs(33, 2, "Failed to start fake CONNECT request for ssl bumped connection: " << connState->tcp); + connState->tcp->close(); } } } @@ -3811,7 +3567,7 @@ certProperties.mimicCert.resetAndLock(mimicCert); ACLFilledChecklist checklist(NULL, sslServerBump->request.getRaw(), - clientConnection != NULL ? clientConnection->rfc931 : dash_str); + tcp != NULL ? tcp->rfc931 : dash_str); checklist.sslErrors = cbdataReference(sslServerBump->sslErrors); for (sslproxy_cert_adapt *ca = Config.ssl_client.cert_adapt; ca != NULL; ca = ca->next) { @@ -3955,7 +3711,7 @@ if (sslContext) { if (!ssl_ctx_cache.add(sslBumpCertKey.termedBuf(), new Ssl::SSL_CTX_Pointer(sslContext))) { // If it is not in storage delete after using. Else storage deleted it. - fd_table[clientConnection->fd].dynamicSslContext = sslContext; + fd_table[tcp->fd].dynamicSslContext = sslContext; } } else { debugs(33, 2, HERE << "Failed to generate SSL cert for " << sslConnectHostOrIp); @@ -3965,8 +3721,8 @@ // If generated ssl context = NULL, try to use static ssl context. if (!sslContext) { if (!port->staticSslContext) { - debugs(83, DBG_IMPORTANT, "Closing SSL " << clientConnection->remote << " as lacking SSL context"); - clientConnection->close(); + debugs(83, DBG_IMPORTANT, "Closing SSL " << tcp->remote << " as lacking SSL context"); + tcp->close(); return; } else { debugs(33, 5, HERE << "Using static ssl context."); @@ -3974,14 +3730,14 @@ } } - if (!httpsCreate(clientConnection, sslContext)) + if (!httpsCreate(tcp, sslContext)) return; // commSetConnTimeout() was called for this request before we switched. // Disable the client read handler until CachePeer selection is complete - Comm::SetSelect(clientConnection->fd, COMM_SELECT_READ, NULL, NULL, 0); - Comm::SetSelect(clientConnection->fd, COMM_SELECT_READ, clientNegotiateSSL, this, 0); + Comm::SetSelect(tcp->fd, COMM_SELECT_READ, NULL, NULL, 0); + Comm::SetSelect(tcp->fd, COMM_SELECT_READ, clientNegotiateSSL, this, 0); switchedToHttps_ = true; } @@ -3995,7 +3751,7 @@ // We are going to read new request flags.readMore = true; - debugs(33, 5, HERE << "converting " << clientConnection << " to SSL"); + debugs(33, 5, "converting " << tcp << " to SSL"); // If sslServerBump is set, then we have decided to deny CONNECT // and now want to switch to SSL to send the error to the client @@ -4005,7 +3761,7 @@ sslServerBump = new Ssl::ServerBump(request); // will call httpsPeeked() with certificate and connection, eventually - FwdState::fwdStart(clientConnection, sslServerBump->entry, sslServerBump->request.getRaw()); + FwdState::fwdStart(tcp, sslServerBump->entry, sslServerBump->request.getRaw()); return; } @@ -4322,7 +4078,7 @@ { ConnStateData * conn = http->getConn(); ACLFilledChecklist *ch = new ACLFilledChecklist(acl, http->request, - cbdataReferenceValid(conn) && conn != NULL && conn->clientConnection != NULL ? conn->clientConnection->rfc931 : dash_str); + cbdataReferenceValid(conn) && conn != NULL && conn->tcp != NULL ? conn->tcp->rfc931 : dash_str); /* * hack for ident ACL. It needs to get full addresses, and a place to store @@ -4337,22 +4093,7 @@ bool ConnStateData::transparent() const { - return clientConnection != NULL && (clientConnection->flags & (COMM_TRANSPARENT|COMM_INTERCEPTION)); -} - -bool -ConnStateData::reading() const -{ - return reader != NULL; -} - -void -ConnStateData::stopReading() -{ - if (reading()) { - comm_read_cancel(clientConnection->fd, reader); - reader = NULL; - } + return tcp != NULL && (tcp->flags & (COMM_TRANSPARENT|COMM_INTERCEPTION)); } BodyPipe::Pointer @@ -4367,7 +4108,7 @@ } int64_t -ConnStateData::mayNeedToReadMoreBody() const +ConnStateData::mayNeedToReadMore() const { if (!bodyPipe) return 0; // request without a body or read/produced all body bytes @@ -4376,7 +4117,7 @@ return -1; // probably need to read more, but we cannot be sure const int64_t needToProduce = bodyPipe->unproducedSize(); - const int64_t haveAvailable = static_cast(in.notYetUsed); + const int64_t haveAvailable = static_cast(inBuf.contentSize()); if (needToProduce <= haveAvailable) return 0; // we have read what we need (but are waiting for pipe space) @@ -4385,26 +4126,6 @@ } void -ConnStateData::stopReceiving(const char *error) -{ - debugs(33, 4, HERE << "receiving error (" << clientConnection << "): " << error << - "; old sending error: " << - (stoppedSending() ? stoppedSending_ : "none")); - - if (const char *oldError = stoppedReceiving()) { - debugs(33, 3, HERE << "already stopped receiving: " << oldError); - return; // nothing has changed as far as this connection is concerned - } - - stoppedReceiving_ = error; - - if (const char *sendError = stoppedSending()) { - debugs(33, 3, HERE << "closing because also stopped sending: " << sendError); - clientConnection->close(); - } -} - -void ConnStateData::expectNoForwarding() { if (bodyPipe != NULL) { @@ -4419,8 +4140,8 @@ { Must(bodyPipe != NULL); debugs(33, 5, HERE << "start dechunking" << bodyPipe->status()); - assert(!in.bodyParser); - in.bodyParser = new ChunkedCodingParser; + assert(!bodyParser_); + bodyParser_ = new ChunkedCodingParser; } /// put parsed content into input buffer and clean up @@ -4442,25 +4163,8 @@ } } - delete in.bodyParser; - in.bodyParser = NULL; -} - -char * -ConnStateData::In::addressToReadInto() const -{ - return buf + notYetUsed; -} - -ConnStateData::In::In() : bodyParser(NULL), - buf (NULL), notYetUsed (0), allocatedSize (0) -{} - -ConnStateData::In::~In() -{ - if (allocatedSize) - memFreeBuf(allocatedSize, buf); - delete bodyParser; // TODO: pool + delete bodyParser_; + bodyParser_ = NULL; } void @@ -4478,7 +4182,7 @@ } debugs(33, 3, HERE << " closing due to missing context for 1xx"); - clientConnection->close(); + tcp->close(); } /// Our close handler called by Comm when the pinned connection is closed @@ -4491,9 +4195,9 @@ pinning.closeHandler = NULL; // Comm unregisters handlers before calling const bool sawZeroReply = pinning.zeroReply; // reset when unpinning unpinConnection(); - if (sawZeroReply && clientConnection != NULL) { + if (sawZeroReply && tcp != NULL) { debugs(33, 3, "Closing client connection on pinned zero reply."); - clientConnection->close(); + tcp->close(); } } @@ -4531,8 +4235,8 @@ char stmp[MAX_IPSTRLEN]; snprintf(desc, FD_DESC_SZ, "%s pinned connection for %s (%d)", (auth || !aPeer) ? pinnedHost : aPeer->name, - clientConnection->remote.toUrl(stmp,MAX_IPSTRLEN), - clientConnection->fd); + tcp->remote.toUrl(stmp,MAX_IPSTRLEN), + tcp->fd); fd_note(pinning.serverConnection->fd, desc); typedef CommCbMemFunT Dialer; @@ -4592,8 +4296,8 @@ // If we are still sending data to the client, do not close now. When we are done sending, // ClientSocketContext::keepaliveNextRequest() checks pinning.serverConnection and will close. // However, if we are idle, then we must close to inform the idle client and minimize races. - if (clientIsIdle && clientConnection != NULL) - clientConnection->close(); + if (clientIsIdle && tcp != NULL) + tcp->close(); } const Comm::ConnectionPointer === modified file 'src/client_side.h' --- src/client_side.h 2013-08-22 18:39:41 +0000 +++ src/client_side.h 2013-10-25 14:12:53 +0000 @@ -34,6 +34,7 @@ #define SQUID_CLIENTSIDE_H #include "comm.h" +#include "comm/TcpReceiver.h" #include "HttpControlMsg.h" #include "HttpParser.h" #if USE_AUTH @@ -181,22 +182,18 @@ * * If the above can be confirmed accurate we can call this object PipelineManager or similar */ -class ConnStateData : public BodyProducer, public HttpControlMsgSink +class ConnStateData : public Comm::TcpReceiver, public BodyProducer, public HttpControlMsgSink { public: explicit ConnStateData(const MasterXaction::Pointer &xact); ~ConnStateData(); - void readSomeData(); - int getAvailableBufferLength() const; bool areAllContextsForThisConnection() const; void freeAllContexts(); - void notifyAllContexts(const int xerrno); ///< tell everybody about the err /// Traffic parsing bool clientParseRequests(); void readNextRequest(); - bool maybeMakeSpaceAvailable(); ClientSocketContext::Pointer getCurrentContext() const; void addContextToQueue(ClientSocketContext * context); int getConcurrentRequestCount() const; @@ -206,27 +203,14 @@ // HttpControlMsgSink API virtual void sendControlMsg(HttpControlMsg msg); - // Client TCP connection details from comm layer. - Comm::ConnectionPointer clientConnection; - - struct In { - In(); - ~In(); - char *addressToReadInto() const; - - ChunkedCodingParser *bodyParser; ///< parses chunked request body - char *buf; - size_t notYetUsed; - size_t allocatedSize; - } in; - - /** number of body bytes we need to comm_read for the "current" request + /** Number of body bytes we need to comm_read for the "current" request. + * Request messages can be aborted. Only incomplete body matter here. * * \retval 0 We do not need to read any [more] body bytes * \retval negative May need more but do not know how many; could be zero! * \retval positive Need to read exactly that many more body bytes */ - int64_t mayNeedToReadMoreBody() const; + virtual int64_t mayNeedToReadMore() const; #if USE_AUTH /** @@ -275,17 +259,6 @@ AnyP::PortCfg *port; bool transparent() const; - bool reading() const; - void stopReading(); ///< cancels comm_read if it is scheduled - - /// true if we stopped receiving the request - const char *stoppedReceiving() const { return stoppedReceiving_; } - /// true if we stopped sending the response - const char *stoppedSending() const { return stoppedSending_; } - /// note request receiving error and close as soon as we write the response - void stopReceiving(const char *error); - /// note response sending error and close as soon as we read the request - void stopSending(const char *error); void expectNoForwarding(); ///< cleans up virgin request [body] forwarding state @@ -293,8 +266,7 @@ virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer); virtual void noteBodyConsumerAborted(BodyPipe::Pointer); - bool handleReadData(char *buf, size_t size); - bool handleRequestBodyData(); + bool processRequestBodyData(MemBuf &aBuf); /** * Correlate the current ConnStateData object with the pinning_fd socket descriptor. @@ -322,12 +294,10 @@ void clientPinnedConnectionClosed(const CommCloseCbParams &io); // comm callbacks - void clientReadRequest(const CommIoCbParams &io); - void connStateClosed(const CommCloseCbParams &io); void requestTimeout(const CommTimeoutCbParams ¶ms); // AsyncJob API - virtual bool doneAll() const { return BodyProducer::doneAll() && false;} + virtual bool doneAll() const {return BodyProducer::doneAll() && Comm::TcpReceiver::doneAll();} virtual void swanSong(); /// Changes state so that we close the connection and quit after serving @@ -388,9 +358,12 @@ void clientPinnedConnectionRead(const CommIoCbParams &io); private: - int connReadWasError(comm_err_t flag, int size, int xerrno); - int connFinishedWithConn(int size); - void clientAfterReadingRequests(); + // Comm::TcpReceiver API + virtual bool processReadBuffer(MemBuf &aBuf); + virtual void noteTcpReadError(int xerrno); + virtual const char * maybeFinishedWithTcp(); + + bool processRequestMessageData(MemBuf &aBuf); bool concurrentRequestQueueFilled() const; #if USE_AUTH @@ -414,14 +387,10 @@ Ssl::CertSignAlgorithm signAlgorithm; ///< The signing algorithm to use #endif - /// the reason why we no longer write the response or nil - const char *stoppedSending_; - /// the reason why we no longer read the request or nil - const char *stoppedReceiving_; - - AsyncCall::Pointer reader; ///< set when we are reading BodyPipe::Pointer bodyPipe; // set when we are reading request body + ChunkedCodingParser *bodyParser_; ///< parses chunked request body + CBDATA_CLASS2(ConnStateData); }; === modified file 'src/client_side_reply.cc' --- src/client_side_reply.cc 2013-10-01 23:21:17 +0000 +++ src/client_side_reply.cc 2013-10-13 09:40:55 +0000 @@ -288,7 +288,7 @@ * A refcounted pointer so that FwdState stays around as long as * this clientReplyContext does */ - Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->clientConnection : NULL; + Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->tcp : NULL; FwdState::Start(conn, http->storeEntry(), http->request, http->al); /* Register with storage manager to receive updates when data comes in. */ @@ -646,7 +646,7 @@ /// Deny loops if (r->flags.loopDetected) { http->al->http.code = Http::scForbidden; - err = clientBuildError(ERR_ACCESS_DENIED, Http::scForbidden, NULL, http->getConn()->clientConnection->remote, http->request); + err = clientBuildError(ERR_ACCESS_DENIED, Http::scForbidden, NULL, http->getConn()->tcp->remote, http->request); createStoreEntry(r->method, RequestFlags()); errorAppendEntry(http->storeEntry(), err); triggerInitialStoreRead(); @@ -673,7 +673,7 @@ assert(r->clientConnectionManager == http->getConn()); /** Start forwarding to get the new object from network */ - Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->clientConnection : NULL; + Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->tcp : NULL; FwdState::Start(conn, http->storeEntry(), r, http->al); } } @@ -691,7 +691,7 @@ RequestMethodStr(http->request->method) << " " << http->uri << "'"); http->al->http.code = Http::scGateway_Timeout; ErrorState *err = clientBuildError(ERR_ONLY_IF_CACHED_MISS, Http::scGateway_Timeout, NULL, - http->getConn()->clientConnection->remote, http->request); + http->getConn()->tcp->remote, http->request); removeClientStoreReference(&sc, http); startError(err); } @@ -858,7 +858,7 @@ if (EBIT_TEST(entry->flags, ENTRY_SPECIAL)) { http->logType = LOG_TCP_DENIED; ErrorState *err = clientBuildError(ERR_ACCESS_DENIED, Http::scForbidden, NULL, - http->getConn()->clientConnection->remote, http->request); + http->getConn()->tcp->remote, http->request); startError(err); return; } @@ -896,7 +896,7 @@ if (!Config2.onoff.enable_purge) { http->logType = LOG_TCP_DENIED; - ErrorState *err = clientBuildError(ERR_ACCESS_DENIED, Http::scForbidden, NULL, http->getConn()->clientConnection->remote, http->request); + ErrorState *err = clientBuildError(ERR_ACCESS_DENIED, Http::scForbidden, NULL, http->getConn()->tcp->remote, http->request); startError(err); return; } @@ -1728,11 +1728,11 @@ assert(http->out.offset == 0); if (Ip::Qos::TheConfig.isHitTosActive()) { - Ip::Qos::doTosLocalHit(http->getConn()->clientConnection); + Ip::Qos::doTosLocalHit(http->getConn()->tcp); } if (Ip::Qos::TheConfig.isHitNfmarkActive()) { - Ip::Qos::doNfmarkLocalHit(http->getConn()->clientConnection); + Ip::Qos::doNfmarkLocalHit(http->getConn()->tcp); } localTempBuffer.offset = reqofs; @@ -1833,7 +1833,7 @@ tmp_noaddr.setNoAddr(); // TODO: make a global const http->logType = LOG_TCP_DENIED_REPLY; ErrorState *err = clientBuildError(ERR_TOO_BIG, Http::scForbidden, NULL, - http->getConn() != NULL ? http->getConn()->clientConnection->remote : tmp_noaddr, + http->getConn() != NULL ? http->getConn()->tcp->remote : tmp_noaddr, http->request); removeClientStoreReference(&(sc), http); HTTPMSGUNLOCK(reply); @@ -1848,7 +1848,7 @@ http->logType = LOG_TCP_HIT; ErrorState *const err = clientBuildError(ERR_PRECONDITION_FAILED, Http::scPreconditionFailed, - NULL, http->getConn()->clientConnection->remote, http->request); + NULL, http->getConn()->tcp->remote, http->request); removeClientStoreReference(&sc, http); HTTPMSGUNLOCK(reply); startError(err); @@ -1955,7 +1955,7 @@ Ip::Address tmp_noaddr; tmp_noaddr.setNoAddr(); err = clientBuildError(page_id, Http::scForbidden, NULL, - http->getConn() != NULL ? http->getConn()->clientConnection->remote : tmp_noaddr, + http->getConn() != NULL ? http->getConn()->tcp->remote : tmp_noaddr, http->request); removeClientStoreReference(&sc, http); @@ -2051,11 +2051,11 @@ return; } if (!conn->isOpen()) { - debugs(33,3, "not sending more data to closing connection " << conn->clientConnection); + debugs(33,3, "not sending more data to closing connection " << conn->tcp); return; } if (conn->pinning.zeroReply) { - debugs(33,3, "not sending more data after a pinned zero reply " << conn->clientConnection); + debugs(33,3, "not sending more data after a pinned zero reply " << conn->tcp); return; } @@ -2067,12 +2067,12 @@ memcpy(buf, result.data, result.length); } - if (reqofs==0 && !logTypeIsATcpHit(http->logType) && Comm::IsConnOpen(conn->clientConnection)) { + if (reqofs==0 && !logTypeIsATcpHit(http->logType) && Comm::IsConnOpen(conn->tcp)) { if (Ip::Qos::TheConfig.isHitTosActive()) { - Ip::Qos::doTosLocalMiss(conn->clientConnection, http->request->hier.code); + Ip::Qos::doTosLocalMiss(conn->tcp, http->request->hier.code); } if (Ip::Qos::TheConfig.isHitNfmarkActive()) { - Ip::Qos::doNfmarkLocalMiss(conn->clientConnection, http->request->hier.code); + Ip::Qos::doNfmarkLocalMiss(conn->tcp, http->request->hier.code); } } @@ -2095,7 +2095,7 @@ reqofs << " bytes (" << result.length << " new bytes)"); debugs(88, 5, "clientReplyContext::sendMoreData:" - << conn->clientConnection << + << conn->tcp << " '" << entry->url() << "'" << " out.offset=" << http->out.offset); === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2013-12-04 00:57:34 +0000 +++ src/client_side_request.cc 2013-12-02 05:20:56 +0000 @@ -163,10 +163,10 @@ start_time = current_time; setConn(aConn); al = new AccessLogEntry; - al->tcpClient = clientConnection = aConn->clientConnection; + al->tcpClient = clientConnection = aConn->tcp; #if USE_SSL - if (aConn->clientConnection != NULL && aConn->clientConnection->isOpen()) { - if (SSL *ssl = fd_table[aConn->clientConnection->fd].ssl) + if (aConn->tcp != NULL && aConn->tcp->isOpen()) { + if (SSL *ssl = fd_table[aConn->tcp->fd].ssl) al->cache.sslClientCert.reset(SSL_get_peer_certificate(ssl)); } #endif @@ -529,7 +529,7 @@ void ClientRequestContext::hostHeaderIpVerify(const ipcache_addrs* ia, const DnsLookupDetails &dns) { - Comm::ConnectionPointer clientConn = http->getConn()->clientConnection; + Comm::ConnectionPointer clientConn = http->getConn()->tcp; // note the DNS details for the transaction stats. http->request->recordLookup(dns); @@ -556,7 +556,7 @@ // IP address validation for Host: failed. Admin wants to ignore them. // NP: we do not yet handle CONNECT tunnels well, so ignore for them if (!Config.onoff.hostStrictVerify && http->request->method != Http::METHOD_CONNECT) { - debugs(85, 3, "SECURITY ALERT: Host header forgery detected on " << http->getConn()->clientConnection << + debugs(85, 3, "SECURITY ALERT: Host header forgery detected on " << http->getConn()->tcp << " (" << A << " does not match " << B << ") on URL: " << urlCanonical(http->request)); // NP: it is tempting to use 'flags.noCache' but that is all about READing cache data. @@ -570,7 +570,7 @@ } debugs(85, DBG_IMPORTANT, "SECURITY ALERT: Host header forgery detected on " << - http->getConn()->clientConnection << " (" << A << " does not match " << B << ")"); + http->getConn()->tcp << " (" << A << " does not match " << B << ")"); debugs(85, DBG_IMPORTANT, "SECURITY ALERT: By user agent: " << http->request->header.getStr(HDR_USER_AGENT)); debugs(85, DBG_IMPORTANT, "SECURITY ALERT: on URL: " << urlCanonical(http->request)); @@ -580,7 +580,7 @@ assert (repContext); repContext->setReplyToError(ERR_CONFLICT_HOST, Http::scConflict, http->request->method, NULL, - http->getConn()->clientConnection->remote, + http->getConn()->tcp->remote, http->request, NULL, #if USE_AUTH @@ -648,8 +648,8 @@ debugs(85, 3, HERE << "validate host=" << host << ", port=" << port << ", portStr=" << (portStr?portStr:"NULL")); if (http->request->flags.intercepted || http->request->flags.interceptTproxy) { // verify the Host: port (if any) matches the apparent destination - if (portStr && port != http->getConn()->clientConnection->local.port()) { - debugs(85, 3, HERE << "FAIL on validate port " << http->getConn()->clientConnection->local.port() << + if (portStr && port != http->getConn()->tcp->local.port()) { + debugs(85, 3, "FAIL on validate port " << http->getConn()->tcp->local.port() << " matches Host: port " << port << " (" << portStr << ")"); hostHeaderVerifyFailed("intercepted port", portStr); } else { @@ -818,7 +818,7 @@ tmpnoaddr.setNoAddr(); error = clientBuildError(page_id, status, NULL, - http->getConn() != NULL ? http->getConn()->clientConnection->remote : tmpnoaddr, + http->getConn() != NULL ? http->getConn()->tcp->remote : tmpnoaddr, http->request ); @@ -849,10 +849,10 @@ Adaptation::Icap::History::Pointer ih = request->icapHistory(); if (ih != NULL) { if (getConn() != NULL) { - ih->rfc931 = getConn()->clientConnection->rfc931; + ih->rfc931 = getConn()->tcp->rfc931; #if USE_SSL - assert(getConn()->clientConnection != NULL); - ih->ssluser = sslGetUserEmail(fd_table[getConn()->clientConnection->fd].ssl); + assert(getConn()->tcp != NULL); + ih->ssluser = sslGetUserEmail(fd_table[getConn()->tcp->fd].ssl); #endif } ih->log_uri = log_uri; @@ -1334,8 +1334,8 @@ /* FIXME PIPELINE: This is innacurate during pipelining */ - if (http->getConn() != NULL && Comm::IsConnOpen(http->getConn()->clientConnection)) - fd_note(http->getConn()->clientConnection->fd, http->uri); + if (http->getConn() != NULL && Comm::IsConnOpen(http->getConn()->tcp)) + fd_note(http->getConn()->tcp->fd, http->uri); assert(http->uri); @@ -1572,7 +1572,7 @@ if (errflag) { debugs(85, 3, HERE << "CONNECT response failure in SslBump: " << errflag); - getConn()->clientConnection->close(); + getConn()->tcp->close(); return; } @@ -1594,7 +1594,7 @@ ClientHttpRequest::sslBumpStart() { debugs(85, 5, HERE << "Confirming " << Ssl::bumpMode(sslBumpNeed_) << - "-bumped CONNECT tunnel on FD " << getConn()->clientConnection); + "-bumped CONNECT tunnel on FD " << getConn()->tcp); getConn()->sslBumpMode = sslBumpNeed_; // send an HTTP 200 response to kick client SSL negotiation @@ -1602,7 +1602,7 @@ static const char *const conn_established = "HTTP/1.1 200 Connection established\r\n\r\n"; AsyncCall::Pointer call = commCbCall(85, 5, "ClientSocketContext::sslBumpEstablish", CommIoCbPtrFun(&SslBumpEstablish, this)); - Comm::Write(getConn()->clientConnection, conn_established, strlen(conn_established), call, NULL); + Comm::Write(getConn()->tcp, conn_established, strlen(conn_established), call, NULL); } #endif @@ -1761,25 +1761,25 @@ if (!calloutContext->tosToClientDone) { calloutContext->tosToClientDone = true; - if (getConn() != NULL && Comm::IsConnOpen(getConn()->clientConnection)) { + if (getConn() != NULL && Comm::IsConnOpen(getConn()->tcp)) { ACLFilledChecklist ch(NULL, request, NULL); ch.src_addr = request->client_addr; ch.my_addr = request->my_addr; tos_t tos = aclMapTOS(Ip::Qos::TheConfig.tosToClient, &ch); if (tos) - Ip::Qos::setSockTos(getConn()->clientConnection, tos); + Ip::Qos::setSockTos(getConn()->tcp, tos); } } if (!calloutContext->nfmarkToClientDone) { calloutContext->nfmarkToClientDone = true; - if (getConn() != NULL && Comm::IsConnOpen(getConn()->clientConnection)) { + if (getConn() != NULL && Comm::IsConnOpen(getConn()->tcp)) { ACLFilledChecklist ch(NULL, request, NULL); ch.src_addr = request->client_addr; ch.my_addr = request->my_addr; nfmark_t mark = aclMapNfmark(Ip::Qos::TheConfig.nfmarkToClient, &ch); if (mark) - Ip::Qos::setSockNfmark(getConn()->clientConnection, mark); + Ip::Qos::setSockNfmark(getConn()->tcp, mark); } } @@ -2026,7 +2026,7 @@ debugs(85,3, HERE << "REQMOD body production failed"); if (request_satisfaction_mode) { // too late to recover or serve an error request->detailError(ERR_ICAP_FAILURE, ERR_DETAIL_CLT_REQMOD_RESP_BODY); - const Comm::ConnectionPointer c = getConn()->clientConnection; + const Comm::ConnectionPointer c = getConn()->tcp; Must(Comm::IsConnOpen(c)); c->close(); // drastic, but we may be writing a response already } else { @@ -2065,7 +2065,7 @@ ConnStateData * c = getConn(); calloutContext->error = clientBuildError(ERR_ICAP_FAILURE, Http::scInternalServerError, NULL, - c != NULL ? c->clientConnection->remote : noAddr, + c != NULL ? c->tcp->remote : noAddr, request ); #if USE_AUTH === modified file 'src/esi/Esi.cc' --- src/esi/Esi.cc 2013-10-25 00:13:46 +0000 +++ src/esi/Esi.cc 2013-10-29 02:33:43 +0000 @@ -1452,8 +1452,8 @@ /* don't honour range requests - for errors we send it all */ flags.error = 1; /* create an error object */ - // XXX: with the in-direction on remote IP. does the http->getConn()->clientConnection exist? - ErrorState * err = clientBuildError(errorpage, errorstatus, NULL, http->getConn()->clientConnection->remote, http->request); + // XXX: with the in-direction on remote IP. does the http->getConn()->tcp exist? + ErrorState * err = clientBuildError(errorpage, errorstatus, NULL, http->getConn()->tcp->remote, http->request); err->err_msg = errormessage; errormessage = NULL; rep = err->BuildHttpReply(); === modified file 'src/external_acl.cc' --- src/external_acl.cc 2013-11-29 04:41:07 +0000 +++ src/external_acl.cc 2013-12-01 21:31:45 +0000 @@ -1019,14 +1019,14 @@ #if USE_SQUID_EUI case _external_acl_format::EXT_ACL_SRCEUI48: - if (request->clientConnectionManager.valid() && request->clientConnectionManager->clientConnection != NULL && - request->clientConnectionManager->clientConnection->remoteEui48.encode(buf, sizeof(buf))) + if (request->clientConnectionManager.valid() && request->clientConnectionManager->tcp != NULL && + request->clientConnectionManager->tcp->remoteEui48.encode(buf, sizeof(buf))) str = buf; break; case _external_acl_format::EXT_ACL_SRCEUI64: - if (request->clientConnectionManager.valid() && request->clientConnectionManager->clientConnection != NULL && - request->clientConnectionManager->clientConnection->remoteEui64.encode(buf, sizeof(buf))) + if (request->clientConnectionManager.valid() && request->clientConnectionManager->tcp != NULL && + request->clientConnectionManager->tcp->remoteEui64.encode(buf, sizeof(buf))) str = buf; break; #endif @@ -1116,8 +1116,8 @@ case _external_acl_format::EXT_ACL_USER_CERT_RAW: - if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConnection)) { - SSL *ssl = fd_table[ch->conn()->clientConnection->fd].ssl; + if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->tcp)) { + SSL *ssl = fd_table[ch->conn()->tcp->fd].ssl; if (ssl) str = sslGetUserCertificatePEM(ssl); @@ -1127,8 +1127,8 @@ case _external_acl_format::EXT_ACL_USER_CERTCHAIN_RAW: - if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConnection)) { - SSL *ssl = fd_table[ch->conn()->clientConnection->fd].ssl; + if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->tcp)) { + SSL *ssl = fd_table[ch->conn()->tcp->fd].ssl; if (ssl) str = sslGetUserCertificateChainPEM(ssl); @@ -1138,8 +1138,8 @@ case _external_acl_format::EXT_ACL_USER_CERT: - if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConnection)) { - SSL *ssl = fd_table[ch->conn()->clientConnection->fd].ssl; + if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->tcp)) { + SSL *ssl = fd_table[ch->conn()->tcp->fd].ssl; if (ssl) str = sslGetUserAttribute(ssl, format->header); @@ -1149,8 +1149,8 @@ case _external_acl_format::EXT_ACL_USER_CA_CERT: - if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConnection)) { - SSL *ssl = fd_table[ch->conn()->clientConnection->fd].ssl; + if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->tcp)) { + SSL *ssl = fd_table[ch->conn()->tcp->fd].ssl; if (ssl) str = sslGetCAAttribute(ssl, format->header); === modified file 'src/format/Format.cc' --- src/format/Format.cc 2013-11-11 12:09:44 +0000 +++ src/format/Format.cc 2013-11-19 22:38:24 +0000 @@ -351,11 +351,11 @@ case LFT_CLIENT_EUI: #if USE_SQUID_EUI // TODO make the ACL checklist have a direct link to any TCP details. - if (al->request && al->request->clientConnectionManager.valid() && al->request->clientConnectionManager->clientConnection != NULL) { - if (al->request->clientConnectionManager->clientConnection->remote.isIPv4()) - al->request->clientConnectionManager->clientConnection->remoteEui48.encode(tmp, 1024); + if (al->request && al->request->clientConnectionManager.valid() && al->request->clientConnectionManager->tcp != NULL) { + if (al->request->clientConnectionManager->tcp->remote.isIPv4()) + al->request->clientConnectionManager->tcp->remoteEui48.encode(tmp, 1024); else - al->request->clientConnectionManager->clientConnection->remoteEui64.encode(tmp, 1024); + al->request->clientConnectionManager->tcp->remoteEui64.encode(tmp, 1024); out = tmp; } #else === modified file 'src/ident/AclIdent.cc' --- src/ident/AclIdent.cc 2013-05-13 22:48:23 +0000 +++ src/ident/AclIdent.cc 2013-10-13 09:12:24 +0000 @@ -86,9 +86,9 @@ ACLFilledChecklist *checklist = Filled(cl); if (checklist->rfc931[0]) { return data->match(checklist->rfc931); - } else if (checklist->conn() != NULL && checklist->conn()->clientConnection != NULL && checklist->conn()->clientConnection->rfc931[0]) { - return data->match(checklist->conn()->clientConnection->rfc931); - } else if (checklist->conn() != NULL && Comm::IsConnOpen(checklist->conn()->clientConnection)) { + } else if (checklist->conn() != NULL && checklist->conn()->tcp != NULL && checklist->conn()->tcp->rfc931[0]) { + return data->match(checklist->conn()->tcp->rfc931); + } else if (checklist->conn() != NULL && Comm::IsConnOpen(checklist->conn()->tcp)) { if (checklist->goAsync(IdentLookup::Instance())) { debugs(28, 3, "switching to ident lookup state"); return -1; @@ -135,9 +135,9 @@ ACLFilledChecklist *checklist = Filled(cl); const ConnStateData *conn = checklist->conn(); // check that ACLIdent::match() tested this lookup precondition - assert(conn && Comm::IsConnOpen(conn->clientConnection)); + assert(conn && Comm::IsConnOpen(conn->tcp)); debugs(28, 3, HERE << "Doing ident lookup" ); - Ident::Start(checklist->conn()->clientConnection, LookupDone, checklist); + Ident::Start(checklist->conn()->tcp, LookupDone, checklist); } void @@ -155,8 +155,8 @@ * Cache the ident result in the connection, to avoid redoing ident lookup * over and over on persistent connections */ - if (checklist->conn() != NULL && checklist->conn()->clientConnection != NULL && !checklist->conn()->clientConnection->rfc931[0]) - xstrncpy(checklist->conn()->clientConnection->rfc931, checklist->rfc931, USER_IDENT_SZ); + if (checklist->conn() != NULL && checklist->conn()->tcp != NULL && !checklist->conn()->tcp->rfc931[0]) + xstrncpy(checklist->conn()->tcp->rfc931, checklist->rfc931, USER_IDENT_SZ); checklist->resumeNonBlockingCheck(IdentLookup::Instance()); } === modified file 'src/peer_select.cc' --- src/peer_select.cc 2013-10-25 00:13:46 +0000 +++ src/peer_select.cc 2013-10-29 02:33:43 +0000 @@ -241,7 +241,7 @@ if (req->clientConnectionManager.valid()) { // construct a "result" adding the ORIGINAL_DST to the set instead of DIRECT Comm::ConnectionPointer p = new Comm::Connection(); - p->remote = req->clientConnectionManager->clientConnection->local; + p->remote = req->clientConnectionManager->tcp->local; p->peerType = fs->code; p->setPeer(fs->_peer); === modified file 'src/redirect.cc' --- src/redirect.cc 2013-11-23 00:58:42 +0000 +++ src/redirect.cc 2013-11-25 23:03:45 +0000 @@ -264,15 +264,15 @@ debugs(61, 5, HERE << "acl-user=" << (r->client_ident?r->client_ident:"NULL")); } - if (!r->client_ident && conn != NULL && conn->clientConnection != NULL && conn->clientConnection->rfc931[0]) { - r->client_ident = conn->clientConnection->rfc931; + if (!r->client_ident && conn != NULL && conn->tcp != NULL && conn->tcp->rfc931[0]) { + r->client_ident = conn->tcp->rfc931; debugs(61, 5, HERE << "ident-user=" << (r->client_ident?r->client_ident:"NULL")); } #if USE_SSL - if (!r->client_ident && conn != NULL && Comm::IsConnOpen(conn->clientConnection)) { - r->client_ident = sslGetUserEmail(fd_table[conn->clientConnection->fd].ssl); + if (!r->client_ident && conn != NULL && Comm::IsConnOpen(conn->tcp)) { + r->client_ident = sslGetUserEmail(fd_table[conn->tcp->fd].ssl); debugs(61, 5, HERE << "ssl-user=" << (r->client_ident?r->client_ident:"NULL")); } #endif @@ -314,8 +314,8 @@ tmpnoaddr.setNoAddr(); repContext->setReplyToError(ERR_GATEWAY_FAILURE, status, http->request->method, NULL, - http->getConn() != NULL && http->getConn()->clientConnection != NULL ? - http->getConn()->clientConnection->remote : tmpnoaddr, + http->getConn() != NULL && http->getConn()->tcp != NULL ? + http->getConn()->tcp->remote : tmpnoaddr, http->request, NULL, #if USE_AUTH === modified file 'src/stat.cc' --- src/stat.cc 2013-11-23 00:58:42 +0000 +++ src/stat.cc 2013-11-25 23:03:45 +0000 @@ -2020,16 +2020,16 @@ storeAppendPrintf(s, "Connection: %p\n", conn); if (conn != NULL) { - const int fd = conn->clientConnection->fd; + const int fd = conn->tcp->fd; storeAppendPrintf(s, "\tFD %d, read %" PRId64 ", wrote %" PRId64 "\n", fd, fd_table[fd].bytes_read, fd_table[fd].bytes_written); storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc); storeAppendPrintf(s, "\tin: buf %p, offset %ld, size %ld\n", - conn->in.buf, (long int) conn->in.notYetUsed, (long int) conn->in.allocatedSize); + conn->inBuf.content(), (long int) conn->inBuf.contentSize(), (long int) conn->inBuf.capacity); storeAppendPrintf(s, "\tremote: %s\n", - conn->clientConnection->remote.toUrl(buf,MAX_IPSTRLEN)); + conn->tcp->remote.toUrl(buf,MAX_IPSTRLEN)); storeAppendPrintf(s, "\tlocal: %s\n", - conn->clientConnection->local.toUrl(buf,MAX_IPSTRLEN)); + conn->tcp->local.toUrl(buf,MAX_IPSTRLEN)); storeAppendPrintf(s, "\tnrequests: %d\n", conn->nrequests); } @@ -2054,13 +2054,13 @@ p = http->request->extacl_user.termedBuf(); } - if (!p && conn != NULL && conn->clientConnection->rfc931[0]) - p = conn->clientConnection->rfc931; + if (!p && conn != NULL && conn->tcp->rfc931[0]) + p = conn->tcp->rfc931; #if USE_SSL - if (!p && conn != NULL && Comm::IsConnOpen(conn->clientConnection)) - p = sslGetUserEmail(fd_table[conn->clientConnection->fd].ssl); + if (!p && conn != NULL && Comm::IsConnOpen(conn->tcp)) + p = sslGetUserEmail(fd_table[conn->tcp->fd].ssl); #endif === modified file 'src/tests/stub_client_side.cc' --- src/tests/stub_client_side.cc 2013-06-27 15:58:46 +0000 +++ src/tests/stub_client_side.cc 2013-10-25 12:09:37 +0000 @@ -28,40 +28,28 @@ void ClientSocketContext::noteIoError(const int xerrno) STUB void ClientSocketContext::writeControlMsg(HttpControlMsg &msg) STUB -void ConnStateData::readSomeData() STUB -int ConnStateData::getAvailableBufferLength() const STUB_RETVAL(0) bool ConnStateData::areAllContextsForThisConnection() const STUB_RETVAL(false) void ConnStateData::freeAllContexts() STUB -void ConnStateData::notifyAllContexts(const int xerrno) STUB +void ConnStateData::noteTcpReadError(const int xerrno) STUB bool ConnStateData::clientParseRequests() STUB_RETVAL(false) void ConnStateData::readNextRequest() STUB -bool ConnStateData::maybeMakeSpaceAvailable() STUB_RETVAL(false) void ConnStateData::addContextToQueue(ClientSocketContext * context) STUB int ConnStateData::getConcurrentRequestCount() const STUB_RETVAL(0) bool ConnStateData::isOpen() const STUB_RETVAL(false) void ConnStateData::checkHeaderLimits() STUB void ConnStateData::sendControlMsg(HttpControlMsg msg) STUB -char *ConnStateData::In::addressToReadInto() const STUB_RETVAL(NULL) -int64_t ConnStateData::mayNeedToReadMoreBody() const STUB_RETVAL(0) #if USE_AUTH void ConnStateData::setAuth(const Auth::UserRequest::Pointer &aur, const char *cause) STUB #endif bool ConnStateData::transparent() const STUB_RETVAL(false) -bool ConnStateData::reading() const STUB_RETVAL(false) -void ConnStateData::stopReading() STUB -void ConnStateData::stopReceiving(const char *error) STUB -void ConnStateData::stopSending(const char *error) STUB void ConnStateData::expectNoForwarding() STUB void ConnStateData::noteMoreBodySpaceAvailable(BodyPipe::Pointer) STUB void ConnStateData::noteBodyConsumerAborted(BodyPipe::Pointer) STUB -bool ConnStateData::handleReadData(char *buf, size_t size) STUB_RETVAL(false) -bool ConnStateData::handleRequestBodyData() STUB_RETVAL(false) +bool ConnStateData::processRequestBodyData(MemBuf &) STUB_RETVAL(false) void ConnStateData::pinConnection(const Comm::ConnectionPointer &pinServerConn, HttpRequest *request, CachePeer *peer, bool auth) STUB void ConnStateData::unpinConnection() STUB const Comm::ConnectionPointer ConnStateData::validatePinnedConnection(HttpRequest *request, const CachePeer *peer) STUB_RETVAL(NULL) void ConnStateData::clientPinnedConnectionClosed(const CommCloseCbParams &io) STUB -void ConnStateData::clientReadRequest(const CommIoCbParams &io) STUB -void ConnStateData::connStateClosed(const CommCloseCbParams &io) STUB void ConnStateData::requestTimeout(const CommTimeoutCbParams ¶ms) STUB void ConnStateData::swanSong() STUB void ConnStateData::quitAfterError(HttpRequest *request) STUB === modified file 'src/tests/stub_libcomm.cc' --- src/tests/stub_libcomm.cc 2013-03-26 10:38:20 +0000 +++ src/tests/stub_libcomm.cc 2013-10-25 11:20:53 +0000 @@ -60,3 +60,18 @@ void Comm::Write(const Comm::ConnectionPointer &conn, MemBuf *mb, AsyncCall::Pointer &callback) STUB void Comm::WriteCancel(const Comm::ConnectionPointer &conn, const char *reason) STUB /*PF*/ void Comm::HandleWrite(int, void*) STUB + +#include "comm/TcpReceiver.h" +//Comm::TcpReceiver::TcpReceiver(const Comm::ConnectionPointer &c); +bool Comm::TcpReceiver::doneAll() const STUB_RETVAL(false) +void Comm::TcpReceiver::swanSong() STUB +void Comm::TcpReceiver::stopReading() STUB +void Comm::TcpReceiver::stopReceiving(const char *error) STUB +void Comm::TcpReceiver::stopSending(const char *error) STUB +bool Comm::TcpReceiver::maybeMakeSpaceAvailable() STUB_RETVAL(false) +void Comm::TcpReceiver::readSomeData() STUB +void Comm::TcpReceiver::readIoHandler(const CommIoCbParams &io) STUB +void Comm::TcpReceiver::tcpConnectionClosed(const CommCloseCbParams &io) STUB +//Comm::ConnectionPointer Comm::TcpReceiver::tcp; +//MemBuf Comm::TcpReceiver::inBuf; +//AsyncCall::Pointer Comm::TcpReceiver::reader; === modified file 'src/tunnel.cc' --- src/tunnel.cc 2013-10-25 00:13:46 +0000 +++ src/tunnel.cc 2013-10-29 02:33:43 +0000 @@ -873,7 +873,7 @@ debugs(26, 4, HERE << "MISS access forbidden."); err = new ErrorState(ERR_FORWARDING_DENIED, Http::scForbidden, request); *status_ptr = Http::scForbidden; - errorSend(http->getConn()->clientConnection, err); + errorSend(http->getConn()->tcp, err); return; } } @@ -890,7 +890,7 @@ tunnelState->request = request; tunnelState->server.size_ptr = size_ptr; tunnelState->status_ptr = status_ptr; - tunnelState->client.conn = http->getConn()->clientConnection; + tunnelState->client.conn = http->getConn()->tcp; tunnelState->al = al; comm_add_close_handler(tunnelState->client.conn->fd,