=== 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<ConnStateData, CommIoCbParams> 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<ConnStateData, CommTimeoutCbParams> 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<ssize_t>(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<mb_size_t>(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<clientReplyContext *>(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<clientReplyContext *>(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<clientReplyContext *>(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<clientReplyContext *>(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<ConnStateData, CommCloseCbParams> 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<Ssl::BumpMode>(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<int64_t>(in.notYetUsed);
+    const int64_t haveAvailable = static_cast<int64_t>(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<ConnStateData, CommCloseCbParams> 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 &params);
 
     // 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 &params) 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,


