]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Merge from trunk. Remove dead files and fluff changes
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 13 May 2011 08:13:01 +0000 (20:13 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 13 May 2011 08:13:01 +0000 (20:13 +1200)
107 files changed:
1  2 
doc/release-notes/release-3.2.sgml
src/CommCalls.cc
src/DelayTagged.cc
src/DelayUser.cc
src/DelayVector.cc
src/HttpRequest.cc
src/HttpRequest.h
src/Makefile.am
src/PeerSelectState.h
src/ProtoPort.cc
src/ProtoPort.h
src/Server.cc
src/Server.h
src/acl/FilledChecklist.cc
src/adaptation/icap/ModXact.cc
src/adaptation/icap/Xaction.cc
src/auth/UserRequest.cc
src/cache_cf.cc
src/cache_manager.cc
src/cf.data.pre
src/client_side.cc
src/client_side.h
src/client_side_reply.cc
src/client_side_request.cc
src/client_side_request.h
src/comm.cc
src/comm/AcceptLimiter.h
src/comm/ConnOpener.cc
src/comm/IoCallback.cc
src/comm/Makefile.am
src/comm/ModPoll.cc
src/comm/ModSelect.cc
src/comm/stub_libcomm.cc
src/defines.h
src/delay_pools.cc
src/dns_internal.cc
src/errorpage.cc
src/errorpage.h
src/esi/Esi.cc
src/eui/Eui48.cc
src/external_acl.cc
src/forward.cc
src/ftp.cc
src/globals.h
src/gopher.cc
src/helper.cc
src/helper.h
src/htcp.cc
src/http.cc
src/icp_v2.cc
src/ip/Intercept.cc
src/ip/Qos.cci
src/ip/QosConfig.cc
src/ipc/Coordinator.cc
src/ipc/Coordinator.h
src/ipc/Forwarder.cc
src/ipc/Forwarder.h
src/ipc/Inquirer.cc
src/ipc/Port.cc
src/ipc/SharedListen.cc
src/ipc/StartListening.h
src/ipc/Strand.cc
src/ipc/UdsOp.cc
src/ipc/UdsOp.h
src/log/FormatSquidCustom.cc
src/log/ModTcp.cc
src/main.cc
src/mgr/Action.cc
src/mgr/Forwarder.cc
src/mgr/Forwarder.h
src/mgr/FunAction.cc
src/mgr/InfoAction.cc
src/mgr/Inquirer.cc
src/mgr/Inquirer.h
src/mgr/Request.cc
src/mgr/Request.h
src/mgr/StoreToCommWriter.cc
src/mgr/StoreToCommWriter.h
src/multicast.cc
src/neighbors.cc
src/pconn.cc
src/peer_select.cc
src/protos.h
src/redirect.cc
src/snmp/Forwarder.cc
src/snmp/Inquirer.cc
src/snmp/Inquirer.h
src/snmp_core.cc
src/snmp_core.h
src/ssl/Makefile.am
src/ssl/stub_libsslsquid.cc
src/ssl/stub_libsslutil.cc
src/stat.cc
src/store.cc
src/structs.h
src/tests/stub_MemObject.cc
src/tests/stub_client_db.cc
src/tests/stub_comm.cc
src/tests/stub_icp.cc
src/tests/stub_ipc.cc
src/tests/stub_store.cc
src/tools.cc
src/tunnel.cc
src/typedefs.h
src/urn.cc
src/wccp.cc
src/whois.cc

Simple merge
index ef9456894c48056c3656b9676e44f8dc57d3b347,3f7da9996bce9c9d840186f36ef9cdaeeed1c973..bd7e8c4afd83803e5b6d20d9b9e7f84bac047b44
@@@ -74,20 -84,10 +74,10 @@@ CommIoCbParams::CommIoCbParams(void *aD
  bool
  CommIoCbParams::syncWithComm()
  {
- #if 0 // transition past??
-     // transition only: read/write legacy code does not know about conn, it just sets FD
-     if (fd >= 0) {
-         if (conn == NULL) {
-             conn = new Comm::Connection;
-             conn->fd = fd;
-         }
-     }
- #endif
      // change parameters if the call was scheduled before comm_close but
      // is being fired after comm_close
 -    if (fd >= 0 && fd_table[fd].closing() && flag != COMM_ERR_CLOSING) {
 -        debugs(5, 3, HERE << "converting late call to COMM_ERR_CLOSING: FD " << fd);
 +    if (conn->fd >= 0 && fd_table[conn->fd].closing() && flag != COMM_ERR_CLOSING) {
 +        debugs(5, 3, HERE << "converting late call to COMM_ERR_CLOSING: " << conn);
          flag = COMM_ERR_CLOSING;
          size = 0;
      }
index a29b749364320ac9438fcf0333ce47d4aecab7d7,a29b749364320ac9438fcf0333ce47d4aecab7d7..5e510a462017567c920101bd0ef72a739ed39ff5
@@@ -39,6 -39,6 +39,7 @@@
  
  #if USE_DELAY_POOLS
  #include "squid.h"
++#include "comm/Connection.h"
  #include "DelayTagged.h"
  #include "NullDelayId.h"
  #include "Store.h"
index 24c20dc2d4f6f4dc22b52214fc978d12187866cd,fbac8e5b3f1a751a3b0929141f3d1a95bcdb0a65..818f9beacf2a26e4816402ccce651de44af39d92
@@@ -42,6 -42,6 +42,7 @@@
  #include "DelayUser.h"
  #include "auth/UserRequest.h"
  #include "auth/User.h"
++#include "comm/Connection.h"
  #include "NullDelayId.h"
  #include "Store.h"
  
index eef4ee630380f2dc4963d6c5aa6c4d476cccefe9,eef4ee630380f2dc4963d6c5aa6c4d476cccefe9..0f286446a813c21a4216c315404ed3b584c7fdac
@@@ -41,6 -41,6 +41,7 @@@
  
  #if USE_DELAY_POOLS
  #include "squid.h"
++#include "comm/Connection.h"
  #include "DelayVector.h"
  #include "CommRead.h"
  
index d5bdbd3e359c8dc08a51a9cb2ad67ead842f51a4,5cfe284de2c96af1287f16cd369b0c8618986f7a..f4ce330caf185c12d658b7ac73b7c5506b6eb626
   */
  
  #include "squid.h"
- #include "acl/FilledChecklist.h"
- #if ICAP_CLIENT
- #include "adaptation/icap/icap_log.h"
- #endif
- #include "auth/UserRequest.h"
 +#include "DnsLookupDetails.h"
- #include "err_detail_type.h"
  #include "HttpRequest.h"
+ #if USE_AUTH
+ #include "auth/UserRequest.h"
+ #endif
  #include "HttpHeaderRange.h"
  #include "MemBuf.h"
  #include "Store.h"
Simple merge
diff --cc src/Makefile.am
index a85b43551aebf6f00f94ee5256b644788d2e7aea,0118aa90e82d53b11ab7081d1b2a497358907b27..778c6345faba935b706fc3658e548d7d3f466afc
@@@ -45,8 -47,8 +47,8 @@@ DIST_SUBDIRS += ip icmp ident log ipc m
  if ENABLE_SSL
  SUBDIRS += ssl
  SSL_LIBS = \
--      ssl/libsslutil.la \
--      ssl/libsslsquid.la
++      ssl/libsslsquid.la \
++      ssl/libsslutil.la
  else
  SSL_LOCAL_LIBS =
  endif
@@@ -1065,11 -1075,17 +1080,19 @@@ tests_testHttpReply_DEPENDENCIES= $(SQU
  ##    Packer.cc \
  ##    StatHist.cc \
  ##    String.cc \
++##
++##    disk.cc \
++##    fs/libfs.la \
  tests_testACLMaxUserIP_SOURCES= \
        cbdata.cc \
        ClientInfo.h \
+       ConfigOption.cc \
        ConfigParser.cc \
 -      disk.cc \
+       DiskIO/ReadRequest.cc \
+       DiskIO/WriteRequest.cc \
        ETag.cc \
+       event.cc \
+       filemap.cc \
        HelperChildConfig.h \
        HelperChildConfig.cc \
        HttpHeader.cc \
  nodist_tests_testACLMaxUserIP_SOURCES= \
        $(TESTSOURCES)
  tests_testACLMaxUserIP_LDADD= \
-       $(COMMON_LIBS) \
+       $(AUTH_ACL_LIBS) \
+       ident/libident.la \
+       acl/libacls.la \
+       eui/libeui.la \
+       acl/libstate.la \
+       $(AUTH_LIBS) \
+       acl/libapi.la \
+       anyp/libanyp.la \
+       base/libbase.la \
+       libsquid.la \
+       ip/libip.la \
 -      fs/libfs.la \
        $(top_builddir)/lib/libmisccontainers.la \
        $(top_builddir)/lib/libmiscencoding.la \
        $(top_builddir)/lib/libmiscutil.la \
@@@ -1293,52 -1364,125 +1370,131 @@@ tests_testCacheManager_DEPENDENCIES = 
        $(REPL_OBJS) \
        $(SQUID_CPPUNIT_LA)
  
++#     tests/stub_CommIO.cc \
++#     tests/stub_comm.cc
  tests_testDiskIO_SOURCES = \
-       $(SWAP_TEST_SOURCES) \
-       ipc.cc \
-       tests/testDiskIO.cc \
-       tests/testDiskIO.h \
-       tests/testMain.cc \
-       tests/stub_cache_manager.cc \
-       tests/stub_client_db.cc \
-       tests/stub_HelperChildConfig.cc \
-       tests/stub_pconn.cc \
-       tests/stub_Port.cc \
-       tests/stub_TypedMsgHdr.cc \
-       tests/stub_UdsOp.cc
- nodist_tests_testDiskIO_SOURCES= \
-       $(TESTSOURCES) \
-       $(DISKIO_GEN_SOURCE) \
-       SquidMath.cc \
-       SquidMath.h \
-       swap_log_op.cc
- tests_testDiskIO_LDADD = \
-       SquidConfig.o \
-       CommCalls.o \
-       DnsLookupDetails.o \
-       auth/libacls.la \
-       ident/libident.la \
-       acl/libacls.la \
-       eui/libeui.la \
-       acl/libstate.la \
-       auth/libauth.la \
-       libsquid.la \
-       fs/libfs.la \
-       ipc/libipc.la \
-       mgr/libmgr.la \
-       $(REPL_OBJS) \
-       $(DISK_LIBS) \
-       $(DISK_OS_LIBS) \
-       acl/libapi.la \
-       comm/libcomm.la \
-       ip/libip.la \
-       ipc/libipc.la \
-       base/libbase.la \
-       $(top_builddir)/lib/libmisccontainers.la \
-       $(top_builddir)/lib/libmiscencoding.la \
-       $(top_builddir)/lib/libmiscutil.la \
-       $(REGEXLIB) \
-       $(SQUID_CPPUNIT_LIBS) \
+       CacheDigest.cc \
+       cbdata.cc \
+       ClientInfo.h \
+       ConfigOption.cc \
+       ConfigParser.cc \
+       $(DELAY_POOL_SOURCE) \
+       $(DISKIO_SOURCE) \
+       disk.cc \
+       ETag.cc \
+       EventLoop.cc \
+       event.cc \
+       fd.cc \
+       filemap.cc \
+       HttpBody.cc \
+       HttpHdrCc.cc \
+       HttpHdrContRange.cc \
+       HttpHdrSc.cc \
+       HttpHdrScTarget.cc \
+       HttpHdrRange.cc \
+       HttpHeaderTools.cc \
+       HttpHeader.cc \
+       HttpMsg.cc \
+       HttpReply.cc \
+       HttpRequestMethod.cc \
+       HttpStatusLine.cc \
+       int.cc \
+       list.cc \
+       MemBuf.cc \
+       MemObject.cc \
+       mem_node.cc \
+       mem.cc \
+       Packer.cc \
+       Parsing.cc \
+       refresh.cc \
+       RemovalPolicy.cc \
+       StatHist.cc \
+       stmem.cc \
+       StoreFileSystem.cc \
+       StoreIOState.cc \
+       StoreMeta.cc \
+       StoreMetaMD5.cc \
+       StoreMetaSTD.cc \
+       StoreMetaSTDLFS.cc \
+       StoreMetaUnpacker.cc \
+       StoreMetaURL.cc \
+       StoreMetaVary.cc \
+       StoreSwapLogData.cc \
+       store_dir.cc \
+       store_io.cc \
+       store_key_md5.cc \
+       store_swapout.cc \
+       store_swapmeta.cc \
+       store.cc \
+       String.cc \
+       SwapDir.cc \
+       tests/stub_access_log.cc \
+       tests/stub_acl.cc \
+       tests/stub_cache_cf.cc \
+       tests/stub_cache_manager.cc \
++      tests/stub_client_db.cc \
+       tests/stub_client_side_request.cc \
 -      tests/stub_comm.cc \
 -      tests/stub_CommIO.cc \
+       tests/stub_debug.cc \
+       tests/stub_errorpage.cc \
+       tests/stub_helper.cc \
+       tests/stub_HelperChildConfig.cc \
+       tests/stub_HttpRequest.cc \
+       tests/stub_http.cc \
+       tests/stub_internal.cc \
++      tests/stub_ipc.cc \
+       tests/stub_mime.cc \
++      tests/stub_pconn.cc \
+       tests/stub_Port.cc \
+       tests/stub_store_client.cc \
+       tests/stub_store_rebuild.cc \
+       tests/stub_tools.cc \
+       tests/stub_TypedMsgHdr.cc \
+       tests/stub_UdsOp.cc \
+       tests/testDiskIO.cc \
+       tests/testDiskIO.h \
+       tests/testMain.cc \
+       tests/testStoreSupport.cc \
+       tests/testStoreSupport.h \
+       time.cc \
+       $(UNLINKDSOURCE) \
+       url.cc \
+       URLScheme.cc \
+       $(WIN32_SOURCE) \
+       wordlist.cc
+ nodist_tests_testDiskIO_SOURCES= \
+       $(TESTSOURCES) \
+       $(DISKIO_GEN_SOURCE) \
+       SquidMath.cc \
+       SquidMath.h \
+       swap_log_op.cc
+ tests_testDiskIO_LDADD = \
+       anyp/libanyp.la \
+       SquidConfig.o \
+       CommCalls.o \
+       DnsLookupDetails.o \
+       $(AUTH_ACL_LIBS) \
+       ident/libident.la \
+       acl/libacls.la \
+       eui/libeui.la \
+       acl/libstate.la \
+       $(AUTH_LIBS) \
 -      base/libbase.la \
+       libsquid.la \
++      comm/libcomm.la \
++      base/libbase.la \
+       ip/libip.la \
+       fs/libfs.la \
++      ipc/libipc.la \
+       $(REPL_OBJS) \
+       $(DISK_LIBS) \
+       $(DISK_OS_LIBS) \
+       acl/libapi.la \
+       mgr/libmgr.la \
++      $(SSL_LIBS) \
+       $(top_builddir)/lib/libmisccontainers.la \
+       $(top_builddir)/lib/libmiscencoding.la \
+       $(top_builddir)/lib/libmiscutil.la \
+       $(REGEXLIB) \
+       $(SQUID_CPPUNIT_LIBS) \
        $(SSLLIB) \
        $(COMPAT_LIB) \
        $(XTRA_LIBS)
@@@ -1985,56 -2185,86 +2197,87 @@@ tests_testHttpRequest_DEPENDENCIES = 
        $(REPL_OBJS) \
        $(SQUID_CPPUNIT_LA)
  
- # TODO:mime.cc drags in HttpReply.cc
- # delay pools need client_side_request.cc
- # store_key_md5 wants the method.
- STORE_TEST_SOURCES=\
-       $(TEST_CALL_SOURCES) \
-       $(DELAY_POOL_SOURCE) \
+ ## why so many sources? well httpHeaderTools requites ACLChecklist & friends.
+ ## first line - what we are testing.
+ tests_testStore_SOURCES= \
        CacheDigest.cc \
+       cbdata.cc \
+       ClientInfo.h \
++      comm/stub_libcomm.cc \
+       ConfigOption.cc \
        ConfigParser.cc \
+       $(DELAY_POOL_SOURCE) \
+       disk.cc \
+       DiskIO/ReadRequest.cc \
+       DiskIO/WriteRequest.cc \
+       ETag.cc \
+       event.cc \
        EventLoop.cc \
+       filemap.cc \
+       HttpHdrCc.cc \
+       HttpHdrContRange.cc \
+       HttpHdrRange.cc \
+       HttpHdrSc.cc \
+       HttpHdrScTarget.cc \
+       HttpHeaderTools.cc \
+       HttpHeader.cc \
        HttpMsg.cc \
+       HttpRequestMethod.cc \
+       int.cc \
+       list.cc \
+       mem.cc \
+       mem_node.cc \
+       MemBuf.cc \
+       Packer.cc \
+       Parsing.cc \
        RemovalPolicy.cc \
-       store_dir.cc \
+       refresh.cc \
+       StatHist.cc \
+       stmem.cc \
        store.cc \
-       HttpRequestMethod.cc \
+       store_dir.cc \
+       store_io.cc \
+       store_swapout.cc \
+       StoreIOState.cc \
+       StoreMeta.cc \
+       StoreMetaMD5.cc \
+       StoreMetaSTD.cc \
+       StoreMetaSTDLFS.cc \
+       StoreMetaUnpacker.cc \
+       StoreMetaURL.cc \
+       StoreMetaVary.cc \
+       StoreSwapLogData.cc \
        store_key_md5.cc \
-       Parsing.cc \
-       ConfigOption.cc \
+       String.cc \
        SwapDir.cc \
-       tests/stub_acl.cc tests/stub_cache_cf.cc \
-       tests/stub_helper.cc cbdata.cc String.cc \
+       tests/CapturingStoreEntry.h \
+       tests/stub_access_log.cc \
+       tests/stub_acl.cc \
+       tests/stub_cache_cf.cc \
+       tests/stub_cache_manager.cc \
+       tests/stub_client_side_request.cc \
        tests/stub_comm.cc \
        tests/stub_debug.cc \
-       tests/stub_client_side_request.cc \
+       tests/stub_DiskIOModule.cc \
+       tests/stub_errorpage.cc \
+       tests/stub_fd.cc \
+       tests/stub_helper.cc \
+       tests/stub_HelperChildConfig.cc \
        tests/stub_http.cc \
-       mem_node.cc \
-       stmem.cc \
+       tests/stub_HttpReply.cc \
+       tests/stub_HttpRequest.cc \
+       tests/stub_MemObject.cc \
        tests/stub_mime.cc \
-       HttpHeaderTools.cc HttpHeader.cc mem.cc  ClientInfo.h \
-       MemBuf.cc HttpHdrContRange.cc Packer.cc HttpHdrCc.cc HttpHdrSc.cc \
-       HttpHdrScTarget.cc url.cc \
-       StatHist.cc HttpHdrRange.cc ETag.cc tests/stub_errorpage.cc \
-       tests/stub_HttpRequest.cc tests/stub_access_log.cc \
-       refresh.cc \
+       tests/stub_Port.cc \
        tests/stub_store_client.cc \
-       tests/stub_tools.cc \
-       tests/testStoreSupport.cc \
-       tests/testStoreSupport.h \
-       time.cc \
-       URLScheme.cc \
-       wordlist.cc
- ## why so many sources? well httpHeaderTools requites ACLChecklist & friends.
- ## first line - what we are testing.
- tests_testStore_SOURCES= \
+       tests/stub_store_rebuild.cc \
        tests/stub_store_swapout.cc \
+       tests/stub_tools.cc \
+       tests/stub_TypedMsgHdr.cc \
+       tests/stub_UdsOp.cc \
        tests/testMain.cc \
-       tests/stub_MemObject.cc \
        tests/testStore.cc \
        tests/testStore.h \
-       tests/CapturingStoreEntry.h \
        tests/testStoreEntryStream.cc \
        tests/testStoreEntryStream.h \
        tests/testStoreController.cc \
@@@ -2102,28 -2345,42 +2358,45 @@@ tests_testString_LDFLAGS = $(LIBADD_DL
  tests_testString_DEPENDENCIES = \
        $(SQUID_CPPUNIT_LA)
  
- SWAP_TEST_SOURCES = \
-       CacheDigest.cc \
-       cbdata.cc \
-       ClientInfo.h \
-       ConfigOption.cc \
-       ConfigParser.cc \
-       disk.cc \
-       ETag.cc \
-       EventLoop.cc \
+ SWAP_TEST_DS =\
+       repl_modules.o \
+       $(DISK_LIBS) \
+       $(AUTH_ACL_LIBS) \
+       ident/libident.la \
+       acl/libacls.la \
+       eui/libeui.la \
+       acl/libstate.la \
+       $(AUTH_LIBS) \
+       acl/libapi.la \
+       base/libbase.la \
+       libsquid.la \
+       ip/libip.la \
+       fs/libfs.la \
+       ipc/libipc.la \
+       mgr/libmgr.la \
+       $(REPL_OBJS) \
+       $(SQUID_CPPUNIT_LA)
+ tests_testUfs_SOURCES = \
+       tests/testUfs.cc \
+       tests/testMain.cc \
+       tests/testUfs.h \
+       tests/stub_cache_manager.cc \
++      tests/stub_client_db.cc \
+       tests/stub_HelperChildConfig.cc \
++      tests/stub_icp.cc \
++      tests/stub_ipc.cc \
++      tests/stub_pconn.cc \
+       tests/stub_Port.cc \
+       tests/stub_TypedMsgHdr.cc \
+       tests/stub_UdsOp.cc \
+       tests/stub_internal.cc \
 -      tests/stub_CommIO.cc \
+       tests/stub_store_rebuild.cc \
        fd.cc \
+       disk.cc \
        filemap.cc \
        HttpBody.cc \
-       HttpHdrContRange.cc \
-       HttpHdrCc.cc \
-       HttpHdrSc.cc \
-       HttpHdrScTarget.cc \
-       HttpHdrRange.cc \
-       HttpHeaderTools.cc \
-       HttpHeader.cc \
-       HttpMsg.cc \
        HttpReply.cc \
-       HttpRequestMethod.cc \
        HttpStatusLine.cc \
        int.cc \
        list.cc \
        StoreMetaVary.cc \
        StoreFileSystem.cc \
        store_io.cc \
-       store_key_md5.cc \
        store_swapout.cc \
        store_swapmeta.cc \
+       $(UNLINKDSOURCE) \
+       $(WIN32_SOURCE) \
+       event.cc \
+       $(DELAY_POOL_SOURCE) \
+       CacheDigest.cc \
+       ConfigParser.cc \
+       EventLoop.cc \
+       HttpMsg.cc \
+       RemovalPolicy.cc \
        store_dir.cc \
        store.cc \
-       String.cc \
+       HttpRequestMethod.cc \
+       store_key_md5.cc \
+       Parsing.cc \
+       ConfigOption.cc \
        SwapDir.cc \
-       tests/stub_access_log.cc \
        tests/stub_acl.cc \
        tests/stub_cache_cf.cc \
-       tests/stub_client_side_request.cc \
-       tests/stub_debug.cc \
-       tests/stub_errorpage.cc \
        tests/stub_helper.cc \
 -      tests/stub_comm.cc \
+       cbdata.cc \
+       String.cc \
+       tests/stub_debug.cc \
+       tests/stub_client_side_request.cc \
        tests/stub_http.cc \
-       tests/stub_HttpRequest.cc \
-       tests/stub_internal.cc \
+       mem_node.cc \
+       stmem.cc \
        tests/stub_mime.cc \
+       HttpHeaderTools.cc \
+       HttpHeader.cc \
+       mem.cc \
+       ClientInfo.h \
+       MemBuf.cc \
+       HttpHdrContRange.cc \
+       Packer.cc \
+       HttpHdrCc.cc \
+       HttpHdrSc.cc \
+       HttpHdrScTarget.cc \
+       url.cc \
+       StatHist.cc \
+       HttpHdrRange.cc \
+       ETag.cc \
+       tests/stub_errorpage.cc \
+       tests/stub_HttpRequest.cc \
+       tests/stub_access_log.cc \
+       refresh.cc \
        tests/stub_store_client.cc \
-       tests/stub_store_rebuild.cc \
        tests/stub_tools.cc \
        tests/testStoreSupport.cc \
        tests/testStoreSupport.h \
@@@ -2207,24 -2460,26 +2475,40 @@@ nodist_tests_testUfs_SOURCES = 
        SquidMath.h \
        swap_log_op.cc
  tests_testUfs_LDADD = \
 -      anyp/libanyp.la \
        CommCalls.o \
        DnsLookupDetails.o \
+       $(AUTH_ACL_LIBS) \
+       ident/libident.la \
+       acl/libacls.la \
+       eui/libeui.la \
+       acl/libstate.la \
+       $(AUTH_LIBS) \
+       acl/libapi.la \
+       base/libbase.la \
+       libsquid.la \
+       ip/libip.la \
+       fs/libfs.la \
+       ipc/libipc.la \
+       mgr/libmgr.la \
        $(REPL_OBJS) \
++      acl/libacls.la \
++      anyp/libanyp.la \
        $(DISK_LIBS) \
        $(DISK_OS_LIBS) \
-       acl/libacls.la \
 +      auth/libacls.la \
 +      ident/libident.la \
 +      eui/libeui.la \
 +      acl/libstate.la \
 +      auth/libauth.la \
        acl/libapi.la \
-       libsquid.la \
-       base/libbase.la \
-       ip/libip.la \
 +      fs/libfs.la \
 +      ipc/libipc.la \
 +      mgr/libmgr.la \
++      libsquid.la \
++      $(SSL_LIBS) \
++      comm/libcomm.la \
++      base/libbase.la \
++      ip/libip.la \
        $(top_builddir)/lib/libmisccontainers.la \
        $(top_builddir)/lib/libmiscencoding.la \
        $(top_builddir)/lib/libmiscutil.la \
@@@ -2258,11 -2604,11 +2633,14 @@@ tests_testCoss_LDADD = 
        $(REPL_OBJS) \
        $(DISK_LIBS) \
        $(DISK_OS_LIBS) \
++      $(COMMON_LIBS) \
++      libsquid.la \
        acl/libapi.la \
        $(top_builddir)/lib/libmisccontainers.la \
        $(top_builddir)/lib/libmiscencoding.la \
        $(top_builddir)/lib/libmiscutil.la \
        $(SQUID_CPPUNIT_LIBS) \
++      $(REGEXLIB) \
        $(SSLLIB) \
        $(COMPAT_LIB) \
        $(XTRA_LIBS)
index 92944f5a7239d094d2a1b143f1575e6f3d063628,49e7386c763cbcaa209d805c83a0d60eeb51c602..b312464450014f32d6278ee9a7be1b24879c5849
  #ifndef   SQUID_PEERSELECTSTATE_H
  #define   SQUID_PEERSELECTSTATE_H
  
 +#include "Array.h"
  #include "cbdata.h"
- #include "ip/Address.h"
 +#include "comm/forward.h"
 +#include "hier_code.h"
  #include "PingData.h"
+ #include "ip/Address.h"
  
 +class HttpRequest;
 +class StoreEntry;
 +
 +typedef void PSC(Comm::ConnectionList *, void *);
 +
 +SQUIDCEXTERN void peerSelect(Comm::ConnectionList *, HttpRequest *, StoreEntry *, PSC *, void *data);
 +SQUIDCEXTERN void peerSelectInit(void);
 +
 +/**
 + * A peer which has been selected as a possible destination.
 + * Listed as pointers here so as to prevent duplicates being added but will
 + * be converted to a set of IP address path options before handing back out
 + * to the caller.
 + *
 + * Certain connection flags and outgoing settings will also be looked up and
 + * set based on the received request and peer settings before handing back.
 + */
 +class FwdServer
 +{
 +public:
 +    peer *_peer;                /* NULL --> origin server */
 +    hier_code code;
 +    FwdServer *next;
 +};
 +
  class ps_state
  {
  
Simple merge
diff --cc src/ProtoPort.h
index c21b95b5f6c9c6dfd8c8a36c1cba55b480e2eba1,323a6d2084b3de3ced6ec77b2ce653dc9d10a8fe..42a4a4ea0759802ae7da32dfe5eae487c3786f9f
@@@ -1,3 -1,6 +1,7 @@@
+ /*
+  * $Id$
+  */
++
  #ifndef SQUID_PROTO_PORT_H
  #define SQUID_PROTO_PORT_H
  
diff --cc src/Server.cc
index dbee8aca6d6c5822a3c0010c2d3a8e263a0ed809,63292c70ad2cd6d566a88b69bfd2928160fcd712..754fc44957f8e50777f6973d455c752751e6e790
   */
  
  #include "squid.h"
+ #include "acl/Gadgets.h"
  #include "base/TextException.h"
 +#include "comm/Connection.h"
 +#include "comm/forward.h"
  #include "comm/Write.h"
  #include "Server.h"
  #include "Store.h"
- //#include "fde.h" /* for fd_table[fd].closing */
 -#include "fde.h" /* for fd_table[fd].closing */
  #include "HttpRequest.h"
  #include "HttpReply.h"
  #include "errorpage.h"
diff --cc src/Server.h
index a314c0419bf7e94b494b2724b762cbbb2da4f0a8,c6b9b5c2df22e5e74fd4c5c38a0ac113a56b9957..4032ac156880dd32a2b36245f30ea8ac9e001ad4
  #ifndef SQUID_SERVER_H
  #define SQUID_SERVER_H
  
- #include "config.h"
+ #include "StoreIOBuffer.h"
+ #include "forward.h"
+ #include "BodyPipe.h"
+ #include "base/AsyncJob.h"
+ #include "CommCalls.h"
 -
  #if USE_ADAPTATION
  #include "adaptation/forward.h"
  #include "adaptation/Initiator.h"
index 56b7c55ad91bb3c87589cfef6f7b5656117df3b3,d85c5387ff0a8a9f3180f2775d756ea4e91c0e35..e061e8c638cd6a159875590bd38b3e506f3203f2
@@@ -2,11 -2,11 +2,13 @@@
  #include "HttpRequest.h"
  #include "HttpReply.h"
  #include "client_side.h"
+ #if USE_AUTH
  #include "auth/UserRequest.h"
  #include "auth/AclProxyAuth.h"
+ #endif
  #include "acl/FilledChecklist.h"
 +#include "comm/Connection.h"
 +#include "comm/forward.h"
  
  CBDATA_CLASS_INIT(ACLFilledChecklist);
  
Simple merge
index da2161622362997659e999cd51883c00c0f13954,7bd9b31f6b5c10541682548d239b772deb48535f..9cd3ae5ea32643b08d22173b2244a5d48841a2b2
@@@ -165,11 -187,13 +165,10 @@@ void Adaptation::Icap::Xaction::closeCo
          }
  
          if (reuseConnection) {
 -            Ip::Address client_addr;
              //status() adds leading spaces.
              debugs(93,3, HERE << "pushing pconn" << status());
-             AsyncCall::Pointer nil;
 -            AsyncCall::Pointer call = NULL;
 -            commSetTimeout(connection, -1, call);
 -            icapPconnPool->push(connection, theService->cfg().host.termedBuf(),
 -                                theService->cfg().port, NULL, client_addr);
 +            commUnsetConnTimeout(connection);
 +            icapPconnPool->push(connection, NULL);
              disableRetries();
          } else {
              //status() adds leading spaces.
@@@ -218,11 -233,11 +217,13 @@@ void Adaptation::Icap::Xaction::dieOnCo
  
  void Adaptation::Icap::Xaction::scheduleWrite(MemBuf &buf)
  {
 +    Must(haveConnection());
 +
      // comm module will free the buffer
      typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommIoCbParams> Dialer;
-     writer = JobCallback(93, 3, Dialer, this, Adaptation::Icap::Xaction::noteCommWrote);
 -    writer = JobCallback(93,3,
++    writer = JobCallback(93, 3,
+                          Dialer, this, Adaptation::Icap::Xaction::noteCommWrote);
      Comm::Write(connection, &buf, writer);
      updateTimeout();
  }
@@@ -327,7 -344,9 +328,9 @@@ void Adaptation::Icap::Xaction::schedul
       * here instead of reading directly into readBuf.buf.
       */
      typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommIoCbParams> Dialer;
-     reader = JobCallback(93, 3, Dialer, this, Adaptation::Icap::Xaction::noteCommRead);
 -    reader = JobCallback(93,3,
++    reader = JobCallback(93, 3,
+                          Dialer, this, Adaptation::Icap::Xaction::noteCommRead);
      comm_read(connection, commBuf, readBuf.spaceSize(), reader);
      updateTimeout();
  }
index bee0f7346d80dbc9b36720066cab7c3f64fa446c,f5637e627adbbce3f082bd64fff352a7c6f2e81c..4744e5d0f4f6b60dcfcf776a32be499276e566bf
  #include "squid.h"
  #include "auth/UserRequest.h"
  #include "auth/User.h"
+ /*#include "auth/Gadgets.h"
+ #include "acl/Acl.h"
+ #include "client_side.h"
+ */
  #include "auth/Config.h"
  #include "auth/Scheme.h"
 +#include "comm/Connection.h"
  #include "HttpReply.h"
  #include "HttpRequest.h"
  
@@@ -342,12 -346,10 +347,12 @@@ AuthUserRequest::authenticate(AuthUserR
      debugs(29, 9, HERE << "header " << (proxy_auth ? proxy_auth : "-") << ".");
  
      if (*auth_user_request == NULL) {
 -        debugs(29, 9, HERE << "This is a new checklist test on FD:" << (conn != NULL ? conn->fd : -1)  );
 +        if (conn != NULL) {
 +            debugs(29, 9, HERE << "This is a new checklist test on:" << conn->clientConnection);
 +        }
  
          if (proxy_auth && request->auth_user_request == NULL && conn != NULL && conn->auth_user_request != NULL) {
-             AuthConfig * scheme = AuthConfig::Find(proxy_auth);
+             Auth::Config * scheme = Auth::Config::Find(proxy_auth);
  
              if (conn->auth_user_request->user() == NULL || conn->auth_user_request->user()->config != scheme) {
                  debugs(29, 1, "WARNING: Unexpected change of authentication scheme from '" <<
diff --cc src/cache_cf.cc
Simple merge
index a4860419b98d9641a9060a2eb726f1907fc21a74,7b23c766ceb1d421dd69f37f5f548b1c015deac1..5f9664432ae8da0916639668b6f1bd8122e0c1e2
@@@ -91,12 -90,12 +91,6 @@@ CacheManager::registerProfile(const Mgr
      }
  }
  
--/**
-- \ingroup CacheManagerAPI
-- * Registers a C-style action, which is implemented as a pointer to a function
-- * taking as argument a pointer to a StoreEntry and returning void.
-- * Implemented via CacheManagerActionLegacy.
-- */
  void
  CacheManager::registerProfile(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic)
  {
@@@ -372,7 -381,7 +382,8 @@@ CacheManager::Start(const Comm::Connect
             actionName << "'" );
  
      if (UsingSmp() && IamWorkerProcess()) {
 -        AsyncJob::Start(new Mgr::Forwarder(fd, cmd->params, request, entry));
++        // is client the right connection to pass here?
 +        AsyncJob::Start(new Mgr::Forwarder(client, cmd->params, request, entry));
          return;
      }
  
diff --cc src/cf.data.pre
Simple merge
index e6a4118958b2a97abfd44ca903600cac8a98c517,622237fffac1357ca5fc2989ddc6e5157dce1813..681c4d9cbef0c8265e5e709cdac7a2a5cdd11d19
  #include "squid.h"
  
  #include "acl/FilledChecklist.h"
+ #if USE_AUTH
  #include "auth/UserRequest.h"
+ #endif
 +#include "base/Subscription.h"
  #include "base/TextException.h"
  #include "ChunkedCodingParser.h"
  #include "client_side.h"
@@@ -189,12 -192,7 +191,11 @@@ static ClientSocketContext *ClientSocke
  /* other */
  static IOCB clientWriteComplete;
  static IOCB clientWriteBodyComplete;
 -static PF clientLifetimeTimeout;
 +static IOACB httpAccept;
 +#if USE_SSL
 +static IOACB httpsAccept;
 +#endif
- static bool clientParseRequest(ConnStateData * conn, bool &do_next_read);
 +static CTCB clientLifetimeTimeout;
  static ClientSocketContext *parseHttpRequestAbort(ConnStateData * conn, const char *uri);
  static ClientSocketContext *parseHttpRequest(ConnStateData *, HttpParser *, HttpRequestMethod *, HttpVersion *);
  #if USE_IDENT
@@@ -611,45 -619,47 +614,47 @@@ prepareLogWithRequestDetails(HttpReques
  void
  ClientHttpRequest::logRequest()
  {
-     if (out.size || logType) {
-         al.icp.opcode = ICP_INVALID;
-         al.url = log_uri;
-         debugs(33, 9, "clientLogRequest: al.url='" << al.url << "'");
-         if (al.reply) {
-             al.http.code = al.reply->sline.status;
-             al.http.content_type = al.reply->content_type.termedBuf();
-         } else if (loggingEntry() && loggingEntry()->mem_obj) {
-             al.http.code = loggingEntry()->mem_obj->getReply()->sline.status;
-             al.http.content_type = loggingEntry()->mem_obj->getReply()->content_type.termedBuf();
-         }
+     if (!out.size && !logType)
+         debugs(33, 5, HERE << "logging half-baked transaction: " << log_uri);
  
-         debugs(33, 9, "clientLogRequest: http.code='" << al.http.code << "'");
+     al.icp.opcode = ICP_INVALID;
+     al.url = log_uri;
+     debugs(33, 9, "clientLogRequest: al.url='" << al.url << "'");
  
-         if (loggingEntry() && loggingEntry()->mem_obj)
-             al.cache.objectSize = loggingEntry()->contentLen();
+     if (al.reply) {
+         al.http.code = al.reply->sline.status;
+         al.http.content_type = al.reply->content_type.termedBuf();
+     } else if (loggingEntry() && loggingEntry()->mem_obj) {
+         al.http.code = loggingEntry()->mem_obj->getReply()->sline.status;
+         al.http.content_type = loggingEntry()->mem_obj->getReply()->content_type.termedBuf();
+     }
  
-         al.cache.caddr.SetNoAddr();
+     debugs(33, 9, "clientLogRequest: http.code='" << al.http.code << "'");
  
-         if (getConn() != NULL) al.cache.caddr = getConn()->log_addr;
+     if (loggingEntry() && loggingEntry()->mem_obj)
+         al.cache.objectSize = loggingEntry()->contentLen();
  
-         al.cache.requestSize = req_sz;
-         al.cache.requestHeadersSize = req_sz;
+     al.cache.caddr.SetNoAddr();
  
-         al.cache.replySize = out.size;
-         al.cache.replyHeadersSize = out.headers_sz;
+     if (getConn() != NULL) al.cache.caddr = getConn()->log_addr;
  
-         al.cache.highOffset = out.offset;
+     al.cache.requestSize = req_sz;
+     al.cache.requestHeadersSize = req_sz;
  
-         al.cache.code = logType;
+     al.cache.replySize = out.size;
+     al.cache.replyHeadersSize = out.headers_sz;
  
-         al.cache.msec = tvSubMsec(start_time, current_time);
+     al.cache.highOffset = out.offset;
  
-         if (request)
-             prepareLogWithRequestDetails(request, &al);
+     al.cache.code = logType;
+     al.cache.msec = tvSubMsec(start_time, current_time);
+     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()->rfc931[0])
 -        al.cache.rfc931 = getConn()->rfc931;
++    if (getConn() != NULL && getConn()->clientConnection != NULL && getConn()->clientConnection->rfc931[0])
++        al.cache.rfc931 = getConn()->clientConnection->rfc931;
  
  #if USE_SSL && 0
  
  
  #endif
  
-         ACLFilledChecklist *checklist = clientAclChecklistCreate(Config.accessList.log, this);
-         if (al.reply)
-             checklist->reply = HTTPMSGLOCK(al.reply);
+     ACLFilledChecklist *checklist = clientAclChecklistCreate(Config.accessList.log, this);
  
-         if (!Config.accessList.log || checklist->fastCheck()) {
-             if (request)
-                 al.adapted_request = HTTPMSGLOCK(request);
-             accessLogLog(&al, checklist);
-             updateCounters();
+     if (al.reply)
+         checklist->reply = HTTPMSGLOCK(al.reply);
  
-             if (getConn() != NULL && getConn()->clientConnection != NULL)
-                 clientdbUpdate(getConn()->clientConnection->remote, logType, PROTO_HTTP, out.size);
-         }
+     if (!Config.accessList.log || checklist->fastCheck()) {
+         if (request)
+             al.adapted_request = HTTPMSGLOCK(request);
+         accessLogLog(&al, checklist);
+         updateCounters();
  
-         delete checklist;
 -        if (getConn() != NULL)
 -            clientdbUpdate(getConn()->peer, logType, AnyP::PROTO_HTTP, out.size);
++        if (getConn() != NULL && getConn()->clientConnection != NULL)
++            clientdbUpdate(getConn()->clientConnection->remote, logType, AnyP::PROTO_HTTP, out.size);
      }
  
+     delete checklist;
      accessLogFreeMemory(&al);
  }
  
@@@ -751,24 -761,20 +755,25 @@@ void ConnStateData::connStateClosed(con
  void
  ConnStateData::swanSong()
  {
 -    debugs(33, 2, "ConnStateData::swanSong: FD " << fd);
 -    fd = -1;
 +    debugs(33, 2, HERE << clientConnection);
-     flags.readMoreRequests = false;
+     flags.readMore = false;
 -    clientdbEstablished(peer, -1);    /* decrement */
 +    clientdbEstablished(clientConnection->remote, -1);        /* decrement */
      assert(areAllContextsForThisConnection());
      freeAllContexts();
+ #if USE_AUTH
      if (auth_user_request != NULL) {
          debugs(33, 4, "ConnStateData::swanSong: freeing auth_user_request '" << auth_user_request << "' (this is '" << this << "')");
          auth_user_request->onConnectionClose(this);
      }
 -    if (pinning.fd >= 0)
 -        comm_close(pinning.fd);
+ #endif
 +
 +    if (Comm::IsConnOpen(pinning.serverConnection))
 +        pinning.serverConnection->close();
 +    pinning.serverConnection = NULL;
 +
 +    if (Comm::IsConnOpen(clientConnection))
 +        clientConnection->close();
 +    clientConnection = NULL;
  
      BodyProducer::swanSong();
      flags.swanSang = true;
  ClientSocketContext::keepaliveNextRequest()
  {
      ConnStateData * conn = http->getConn();
-     bool do_next_read = false;
  
 -    debugs(33, 3, "ClientSocketContext::keepaliveNextRequest: FD " << conn->fd);
 +    debugs(33, 3, HERE << "ConnnStateData(" << conn->clientConnection << "), Context(" << clientConnection << ")");
      connIsFinished();
  
 -    if (conn->pinning.pinned && conn->pinning.fd == -1) {
 -        debugs(33, 2, "clientKeepaliveNextRequest: FD " << conn->fd << " Connection was pinned but server side gone. Terminating client connection");
 -        comm_close(conn->fd);
 +    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();
          return;
      }
  
       * from our read buffer we may never re-register for another client read.
       */
  
-     if (clientParseRequest(conn, do_next_read)) {
+     if (conn->clientParseRequests()) {
 -        debugs(33, 3, "clientSocketContext::keepaliveNextRequest: FD " << conn->fd << ": parsed next request from buffer");
 +        debugs(33, 3, HERE << conn->clientConnection << ": parsed next request from buffer");
      }
  
      /** \par
       */
  
      if ((deferredRequest = conn->getCurrentContext()).getRaw()) {
 -        debugs(33, 3, "ClientSocketContext:: FD " << conn->fd << ": calling PushDeferredIfNeeded");
 +        debugs(33, 3, HERE << conn->clientConnection << ": calling PushDeferredIfNeeded");
          ClientSocketContextPushDeferredIfNeeded(deferredRequest, conn);
-     } else {
+     } else if (conn->flags.readMore) {
 -        debugs(33, 3, "ClientSocketContext:: FD " << conn->fd << ": calling conn->readNextRequest()");
 +        debugs(33, 3, HERE << conn->clientConnection << ": calling conn->readNextRequest()");
          conn->readNextRequest();
 -        debugs(33, DBG_IMPORTANT, HERE << "abandoning FD " << conn->fd);
+     } else {
+         // XXX: Can this happen? CONNECT tunnels have deferredRequest set.
++        debugs(33, DBG_IMPORTANT, HERE << "abandoning " << conn->clientConnection);
      }
  }
  
@@@ -2024,10 -2071,10 +2065,10 @@@ prepareTransparentURL(ConnStateData * c
          /* 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()->me.ToHostname(ipbuf,MAX_IPSTRLEN),
 +        http->getConn()->clientConnection->local.ToHostname(ipbuf,MAX_IPSTRLEN),
-         snprintf(http->uri, url_sz, "%s://%s:%d%s",
-                  http->getConn()->port->protocol,
+         snprintf(http->uri, url_sz, "http://%s:%d%s",
+                  // http->getConn()->port->protocol,
 -                 ipbuf, http->getConn()->me.GetPort(), url);
 +                 ipbuf, http->getConn()->clientConnection->local.GetPort(), url);
          debugs(33, 5, "TRANSPARENT REWRITE: '" << http->uri << "'");
      }
  }
@@@ -2347,21 -2399,12 +2387,12 @@@ ConnStateData::checkHeaderLimits(
  }
  
  void
- ConnStateData::clientMaybeReadData(int do_next_read)
- {
-     if (do_next_read) {
-         flags.readMoreRequests = true;
-         readSomeData();
-     }
- }
- void
- ConnStateData::clientAfterReadingRequests(int do_next_read)
+ ConnStateData::clientAfterReadingRequests()
  {
      // Were we expecting to read more request body from half-closed connection?
 -    if (mayNeedToReadMoreBody() && commIsHalfClosed(fd)) {
 -        debugs(33, 3, HERE << "truncated body: closing half-closed FD " << fd);
 -        comm_close(fd);
 +    if (mayNeedToReadMoreBody() && commIsHalfClosed(clientConnection->fd)) {
 +        debugs(33, 3, HERE << "truncated body: closing half-closed " << clientConnection);
 +        clientConnection->close();
          return;
      }
  
@@@ -2409,12 -2453,14 +2443,14 @@@ clientProcessRequest(ConnStateData *con
      if ((request = HttpRequest::CreateFromUrlAndMethod(http->uri, method)) == NULL) {
          clientStreamNode *node = context->getClientReplyContext();
          debugs(33, 5, "Invalid URL: " << http->uri);
+         // setLogUri should called before repContext->setReplyToError
+         setLogUri(http, http->uri,  true);
          clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
          assert (repContext);
 -        repContext->setReplyToError(ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL);
 +        repContext->setReplyToError(ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, conn->clientConnection->remote, NULL, NULL, NULL);
          assert(context->http->out.offset == 0);
          context->pullData();
-         conn->flags.readMoreRequests = false;
+         conn->flags.readMore = false;
          goto finish;
      }
  
  
          clientStreamNode *node = context->getClientReplyContext();
          debugs(33, 5, "Unsupported HTTP version discovered. :\n" << HttpParserHdrBuf(hp));
+         // setLogUri should called before repContext->setReplyToError
+         setLogUri(http, http->uri,  true);
          clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
          assert (repContext);
 -        repContext->setReplyToError(ERR_UNSUP_HTTPVERSION, HTTP_HTTP_VERSION_NOT_SUPPORTED, method, http->uri, conn->peer, NULL, HttpParserHdrBuf(hp), NULL);
 +        repContext->setReplyToError(ERR_UNSUP_HTTPVERSION, HTTP_HTTP_VERSION_NOT_SUPPORTED, method, http->uri,
 +                                    conn->clientConnection->remote, NULL, HttpParserHdrBuf(hp), NULL);
          assert(context->http->out.offset == 0);
          context->pullData();
-         conn->flags.readMoreRequests = false;
+         conn->flags.readMore = false;
          goto finish;
      }
  
      if (http_ver.major >= 1 && !request->parseHeader(HttpParserHdrBuf(hp), HttpParserHdrSz(hp))) {
          clientStreamNode *node = context->getClientReplyContext();
          debugs(33, 5, "Failed to parse request headers:\n" << HttpParserHdrBuf(hp));
+         // setLogUri should called before repContext->setReplyToError
+         setLogUri(http, http->uri,  true);
          clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
          assert (repContext);
 -        repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL);
 +        repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri, conn->clientConnection->remote, NULL, NULL, NULL);
          assert(context->http->out.offset == 0);
          context->pullData();
-         conn->flags.readMoreRequests = false;
+         conn->flags.readMore = false;
          goto finish;
      }
  
 +    request->clientConnectionManager = conn;
 +
      request->flags.accelerated = http->flags.accel;
+     request->flags.sslBumped = conn->switchedToHttps();
      request->flags.ignore_cc = conn->port->ignore_cc;
      request->flags.no_direct = request->flags.accelerated ? !conn->port->allow_direct : 0;
  
          clientStreamNode *node = context->getClientReplyContext();
          clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
          assert (repContext);
 -        repContext->setReplyToError(ERR_UNSUP_REQ,
 -                                    HTTP_NOT_IMPLEMENTED, request->method, NULL,
 -                                    conn->peer, request, NULL, NULL);
 +        repContext->setReplyToError(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED, request->method, NULL,
 +                                    conn->clientConnection->remote, request, NULL, NULL);
          assert(context->http->out.offset == 0);
          context->pullData();
-         conn->flags.readMoreRequests = false;
+         conn->flags.readMore = false;
          goto finish;
      }
  
          assert (repContext);
          repContext->setReplyToError(ERR_INVALID_REQ,
                                      HTTP_LENGTH_REQUIRED, request->method, NULL,
 -                                    conn->peer, request, NULL, NULL);
 +                                    conn->clientConnection->remote, request, NULL, NULL);
          assert(context->http->out.offset == 0);
          context->pullData();
-         conn->flags.readMoreRequests = false;
+         conn->flags.readMore = false;
          goto finish;
      }
  
              clientStreamNode *node = context->getClientReplyContext();
              clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
              assert (repContext);
 -            repContext->setReplyToError(ERR_INVALID_REQ, HTTP_EXPECTATION_FAILED, request->method,
 -                                        http->uri, conn->peer, request, NULL, NULL);
 +            repContext->setReplyToError(ERR_INVALID_REQ, HTTP_EXPECTATION_FAILED, request->method, http->uri,
 +                                        conn->clientConnection->remote, request, NULL, NULL);
              assert(context->http->out.offset == 0);
              context->pullData();
+             conn->flags.readMore = false;
              goto finish;
          }
      }
              assert (repContext);
              repContext->setReplyToError(ERR_TOO_BIG,
                                          HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL,
 -                                        conn->peer, http->request, NULL, NULL);
 +                                        conn->clientConnection->remote, http->request, NULL, NULL);
              assert(context->http->out.offset == 0);
              context->pullData();
+             conn->flags.readMore = false;
              goto finish;
          }
  
@@@ -2602,11 -2664,11 +2652,10 @@@ finish
       * be freed and the above connNoteUseOfBuffer() would hit an
       * assertion, not to mention that we were accessing freed memory.
       */
 -    if (http->request->flags.resetTCP() && conn->fd > -1) {
 -        debugs(33, 3, HERE << "Sending TCP RST on FD " << conn->fd);
 +    if (http->request->flags.resetTCP() && Comm::IsConnOpen(conn->clientConnection)) {
 +        debugs(33, 3, HERE << "Sending TCP RST on " << conn->clientConnection);
-         conn->flags.readMoreRequests = false;
+         conn->flags.readMore = false;
 -        comm_reset_close(conn->fd);
 -        return;
 +        comm_reset_close(conn->clientConnection);
-         return;
      }
  }
  
@@@ -2636,29 -2700,23 +2685,23 @@@ connOkToAddRequest(ConnStateData * conn
   * Attempt to parse one or more requests from the input buffer.
   * If a request is successfully parsed, even if the next request
   * is only partially parsed, it will return TRUE.
-  * do_next_read is updated to indicate whether a read should be
-  * scheduled.
   */
static bool
clientParseRequest(ConnStateData * conn, bool &do_next_read)
+ bool
ConnStateData::clientParseRequests()
  {
      HttpRequestMethod method;
-     ClientSocketContext *context;
      bool parsed_req = false;
      HttpVersion http_ver;
-     HttpParser hp;
  
-     debugs(33, 5, HERE << conn->clientConnection << ": attempting to parse");
 -    debugs(33, 5, HERE << "FD " << fd << ": attempting to parse");
++    debugs(33, 5, HERE << clientConnection << ": attempting to parse");
  
      // Loop while we have read bytes that are not needed for producing the body
-     // On errors, bodyPipe may become nil, but readMoreRequests will be cleared
-     while (conn->in.notYetUsed > 0 && !conn->bodyPipe &&
-             conn->flags.readMoreRequests) {
-         connStripBufferWhitespace (conn);
+     // On errors, bodyPipe may become nil, but readMore will be cleared
+     while (in.notYetUsed > 0 && !bodyPipe && flags.readMore) {
+         connStripBufferWhitespace(this);
  
          /* Don't try to parse if the buffer is empty */
-         if (conn->in.notYetUsed == 0)
+         if (in.notYetUsed == 0)
              break;
  
          /* Limit the number of concurrent requests to 2 */
  
          /* status -1 or 1 */
          if (context) {
-             debugs(33, 5, HERE << conn->clientConnection << ": parsed a request");
 -            debugs(33, 5, HERE << "FD " << fd << ": parsed a request");
 -            commSetTimeout(fd, Config.Timeout.lifetime, clientLifetimeTimeout,
 -                           context->http);
++            debugs(33, 5, HERE << clientConnection << ": parsed a request");
 +            AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "clientLifetimeTimeout",
 +                                                        CommTimeoutCbPtrFun(clientLifetimeTimeout, context->http));
-             commSetConnTimeout(conn->clientConnection, Config.Timeout.lifetime, timeoutCall);
++            commSetConnTimeout(clientConnection, Config.Timeout.lifetime, timeoutCall);
  
-             clientProcessRequest(conn, &hp, context, method, http_ver);
+             clientProcessRequest(this, &parser_, context, method, http_ver);
  
-             parsed_req = true;
+             parsed_req = true; // XXX: do we really need to parse everything right NOW ?
  
              if (context->mayUseConnection()) {
-                 debugs(33, 3, "clientParseRequest: Not reading, as this request may need the connection");
-                 do_next_read = 0;
+                 debugs(33, 3, HERE << "Not parsing new requests, as this request may need the connection");
                  break;
              }
          }
  void
  ConnStateData::clientReadRequest(const CommIoCbParams &io)
  {
 -    debugs(33,5,HERE << "clientReadRequest FD " << io.fd << " size " << io.size);
 +    debugs(33,5,HERE << io.conn << " size " << io.size);
      Must(reading());
      reader = NULL;
-     bool do_next_read = 1; /* the default _is_ to read data! - adrian */
  
 -    assert (io.fd == fd);
 -
      /* Bail out quickly on COMM_ERR_CLOSING - close handlers will tidy up */
  
      if (io.flag == COMM_ERR_CLOSING) {
              }
  
              /* It might be half-closed, we can't tell */
 -            fd_table[fd].flags.socket_eof = 1;
 +            fd_table[io.conn->fd].flags.socket_eof = 1;
  
 -            commMarkHalfClosed(fd);
 +            commMarkHalfClosed(io.conn->fd);
  
-             do_next_read = 0;
 -            fd_note(fd, "half-closed");
 +            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
  
      /* Process next request */
      if (getConcurrentRequestCount() == 0)
 -        fd_note(fd, "Reading next request");
 +        fd_note(io.fd, "Reading next request");
  
-     if (! clientParseRequest(this, do_next_read)) {
+     if (!clientParseRequests()) {
          if (!isOpen())
              return;
          /*
@@@ -2951,9 -2999,9 +2986,9 @@@ ConnStateData::abortChunkedRequestBody(
      }
  #else
      debugs(33, 3, HERE << "aborting chunked request without error " << error);
 -    comm_reset_close(fd);
 +    comm_reset_close(clientConnection);
  #endif
-     flags.readMoreRequests = false;
+     flags.readMore = false;
  }
  
  void
@@@ -3077,39 -3140,12 +3112,39 @@@ connStateCreate(const Comm::ConnectionP
              debugs(33, 1, "Notice: httpd_accel_no_pmtu_disc not supported on your platform");
              reported = 1;
          }
 +#endif
 +    }
 +
 +    typedef CommCbMemFunT<ConnStateData, CommCloseCbParams> Dialer;
 +    AsyncCall::Pointer call = JobCallback(33, 5, Dialer, result, ConnStateData::connStateClosed);
 +    comm_add_close_handler(client->fd, call);
 +
 +    if (Config.onoff.log_fqdn)
 +        fqdncache_gethostbyaddr(client->remote, FQDN_LOOKUP_IF_MISS);
  
 +#if USE_IDENT
 +    if (Ident::TheConfig.identLookup) {
 +        ACLFilledChecklist identChecklist(Ident::TheConfig.identLookup, NULL, NULL);
 +        identChecklist.src_addr = client->remote;
 +        identChecklist.my_addr = client->local;
 +        if (identChecklist.fastCheck())
 +            Ident::Start(client, clientIdentDone, result);
 +    }
  #endif
  
 +#if USE_SQUID_EUI
 +    if (Eui::TheConfig.euiLookup) {
 +        if (client->remote.IsIPv4()) {
 +            result->clientConnection->remoteEui48.lookup(client->remote);
 +        } else if (client->remote.IsIPv6()) {
 +            result->clientConnection->remoteEui64.lookup(client->remote);
 +        }
      }
 +#endif
 +
 +    clientdbEstablished(client->remote, 1);
  
-     result->flags.readMoreRequests = true;
+     result->flags.readMore = true;
      return result;
  }
  
@@@ -3144,8 -3205,10 +3179,8 @@@ httpAccept(int, const Comm::ConnectionP
  
      connState->readSomeData();
  
 -    clientdbEstablished(details->peer, 1);
 -
  #if USE_DELAY_POOLS
--    fd_table[newfd].clientInfo = NULL;
++    fd_table[details->fd].clientInfo = NULL;
  
      if (Config.onoff.client_db) {
          /* it was said several times that client write limiter does not work if client_db is disabled */
              // TODO: we check early to limit error response bandwith but we
              // should recheck when we can honor delay_pool_uses_indirect
  
--            ch.src_addr = details->peer;
--            ch.my_addr = details->me;
++            ch.src_addr = details->remote;
++            ch.my_addr = details->local;
  
              if (ch.fastCheck()) {
  
                  /*  request client information from db after we did all checks
                      this will save hash lookup if client failed checks */
--                ClientInfo * cli = clientdbGetInfo(details->peer);
++                ClientInfo * cli = clientdbGetInfo(details->remote);
                  assert(cli);
  
                  /* put client info in FDE */
--                fd_table[newfd].clientInfo = cli;
++                fd_table[details->fd].clientInfo = cli;
  
                  /* setup write limiter for this request */
                  const double burst = floor(0.5 +
@@@ -3490,8 -3577,9 +3525,10 @@@ ConnStateData::switchToHttps(const cha
      assert(areAllContextsForThisConnection());
      freeAllContexts();
      //currentobject->connIsFinished();
 -    debugs(33, 5, HERE << "converting FD " << fd << " to SSL");
 +
+     // We are going to read new request
+     flags.readMore = true;
 +    debugs(33, 5, HERE << "converting " << clientConnection << " to SSL");
  
      return getSslContextStart();
  }
@@@ -3626,30 -3735,6 +3661,30 @@@ clientHttpsConnectionsOpen(void
  }
  #endif
  
-     debugs(1, 1, "Accepting" <<
-            (s->intercepted ? " intercepted" : "") <<
-            (s->spoof_client_ip ? " spoofing" : "") <<
-            (s->sslBump ? " bumpy" : "") <<
-            (s->accel ? " accelerated" : "")
 +/// process clientHttpConnectionsOpen result
 +static void
 +clientListenerConnectionOpened(http_port_list *s, const Ipc::FdNoteId portTypeNote, const Subscription::Pointer &sub)
 +{
 +    if (!OpenedHttpSocket(s->listenConn, portTypeNote))
 +        return;
 +
 +    Must(s);
 +    Must(Comm::IsConnOpen(s->listenConn));
 +
 +    // TCP: setup a job to handle accept() with subscribed handler
 +    AsyncJob::Start(new Comm::TcpAcceptor(s->listenConn, FdNote(portTypeNote), sub));
 +
++    debugs(1, 1, "Accepting " <<
++           (s->intercepted ? "NAT intercepted " : "") <<
++           (s->spoof_client_ip ? "TPROXY spoofing " : "") <<
++           (s->sslBump ? "SSL bumped " : "") <<
++           (s->accel ? "reverse-proxy " : "")
 +           << FdNote(portTypeNote) << " connections at "
 +           << s->listenConn);
 +
 +    Must(AddOpenedHttpSocket(s->listenConn)); // otherwise, we have received a fd we did not ask for
 +}
 +
  void
  clientOpenListenSockets(void)
  {
@@@ -3996,17 -4095,11 +4031,11 @@@ ConnStateData::validatePinnedConnection
      }
  
      if (!valid) {
-         /* The pinning info is not safe, remove any pinning info*/
+         /* The pinning info is not safe, remove any pinning info */
          unpinConnection();
-         /* also close the server side socket, we should not use it for invalid/unauthenticated
-            requests...
-          */
-         if (Comm::IsConnOpen(pinning.serverConnection))
-             pinning.serverConnection->close();
      }
  
 -    return pinning.fd;
 +    return pinning.serverConnection;
  }
  
  void
@@@ -4016,12 -4109,11 +4045,13 @@@ ConnStateData::unpinConnection(
          cbdataReferenceDone(pinning.peer);
  
      if (pinning.closeHandler != NULL) {
 -        comm_remove_close_handler(pinning.fd, pinning.closeHandler);
 +        comm_remove_close_handler(pinning.serverConnection->fd, pinning.closeHandler);
          pinning.closeHandler = NULL;
      }
+     /// also close the server side socket, we should not use it for any future requests...
 -    comm_close(pinning.fd);
 -    pinning.fd = -1;
++    pinning.serverConnection->close();
      safe_free(pinning.host);
 +
 +    /* NOTE: pinning.pinned should be kept. This combined with fd == -1 at the end of a request indicates that the host
 +     * connection has gone away */
  }
index 24c11040983d90705d869813eed422037c93a194,dbc8017aeb42825acbbf411f565532f0ad578ee0..aa5961f764c4d77e0e4d217647c2b5c41a0c9b44
@@@ -141,8 -116,8 +115,8 @@@ public
      void writeControlMsg(HttpControlMsg &msg);
  
  protected:
-     static IOCB WroteControlMsg;  //(int fd, char *bufnotused, size_t size, comm_err_t errflag, int xerrno, void *data);
 -    static void WroteControlMsg(int fd, char *bufnotused, size_t size, comm_err_t errflag, int xerrno, void *data);
 -    void wroteControlMsg(int fd, char *bufnotused, size_t size, comm_err_t errflag, int xerrno);
++    static IOCB WroteControlMsg;
 +    void wroteControlMsg(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag, int xerrno);
  
  private:
      CBDATA_CLASS(ClientSocketContext);
  };
  
  
- /**
-  * Manages a connection to a client.
-  *
-  * Multiple requests (up to 2) can be pipelined. This object is responsible for managing
-  * which one is currently being fulfilled and what happens to the queue if the current one
-  * causes the client connection to be closed early.
-  *
-  * Act as a manager for the connection and passes data in buffer to the current parser.
-  * the parser has ambiguous scope at present due to being made from global functions
-  * I believe this object uses the parser to identify boundaries and kick off the
-  * actual HTTP request handling objects (ClientSocketContext, ClientHttpRequest, HttpRequest)
-  *
-  * If the above can be confirmed accurate we can call this object PipelineManager or similar
-  */
 -class ConnectionDetail;
 -
+ /** A connection to a socket */
  class ConnStateData : public BodyProducer, public HttpControlMsgSink
  {
  
@@@ -232,13 -199,21 +197,11 @@@ public
       */
      ClientSocketContext::Pointer currentobject;
  
 -    Ip::Address peer;
 -
 -    Ip::Address me;
 -
      Ip::Address log_addr;
-     /// count of requests made so far on this connection
 -    char rfc931[USER_IDENT_SZ];
      int nrequests;
  
 -#if USE_SQUID_EUI
 -    Eui::Eui48 peer_eui48;
 -    Eui::Eui64 peer_eui64;
 -#endif
 -
      struct {
-         bool readMoreRequests;
+         bool readMore; ///< needs comm_read (for this request or new requests)
          bool swanSang; // XXX: temporary flag to check proper cleanup
      } flags;
      struct {
@@@ -330,13 -306,14 +293,13 @@@ protected
  private:
      int connReadWasError(comm_err_t flag, int size, int xerrno);
      int connFinishedWithConn(int size);
-     void clientMaybeReadData(int do_next_read);
-     void clientAfterReadingRequests(int do_next_read);
+     void clientAfterReadingRequests();
  
  private:
-     CBDATA_CLASS2(ConnStateData);
-     // XXX: CBDATA macro plays with public/private exposing all of the supposedly below private fields...
+     HttpParser parser_;
  
 -    bool transparent_;
+     // XXX: CBDATA plays with public/private and leaves the following 'private' fields all public... :(
+     CBDATA_CLASS2(ConnStateData);
      bool closing_;
  
      bool switchedToHttps_;
index 0f86bc22c59c5a2fb8b0477f81d95ef1181404b9,2680d1175fe7269ab84f9679b4caa19cd857c569..c9a8a58aa9ea16aae3eb03d1e05dab8c41f9b568
@@@ -268,10 -274,11 +274,11 @@@ clientReplyContext::processExpired(
       * A refcounted pointer so that FwdState stays around as long as
       * this clientReplyContext does
       */
 -    FwdState::fwdStart(http->getConn() != NULL ? http->getConn()->fd : -1,
 -                       http->storeEntry(),
 -                       http->request);
 +    Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->clientConnection : NULL;
 +    FwdState::fwdStart(conn, http->storeEntry(), http->request);
 +
      /* Register with storage manager to receive updates when data comes in. */
      if (EBIT_TEST(entry->flags, ENTRY_ABORTED))
          debugs(88, 0, "clientReplyContext::processExpired: Found ENTRY_ABORTED object");
  
@@@ -650,13 -657,14 +657,13 @@@ clientReplyContext::processMiss(
  
          /** Check for internal requests. Update Protocol info if so. */
          if (http->flags.internal)
-             r->protocol = PROTO_INTERNAL;
+             r->protocol = AnyP::PROTO_INTERNAL;
  
-         r->clientConnectionManager = http->getConn();
+         assert(r->clientConnectionManager == http->getConn());
  
          /** Start forwarding to get the new object from network */
 -        FwdState::fwdStart(http->getConn() != NULL ? http->getConn()->fd : -1,
 -                           http->storeEntry(),
 -                           r);
 +        Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->clientConnection : NULL;
 +        FwdState::fwdStart(conn, http->storeEntry(), r);
      }
  }
  
index 4d4d540a8d96853f5d747504640b24636c6b81ef,5d4565b9e14f5dffda4725ae3de14f5d3a15b31c..1a1169ea6b8b6ed494ee671920f94532852ab33d
@@@ -631,12 -646,15 +650,15 @@@ ClientRequestContext::clientAccessCheck
          tmpnoaddr.SetNoAddr();
          repContext->setReplyToError(page_id, status,
                                      http->request->method, NULL,
 -                                    http->getConn() != NULL ? http->getConn()->peer : tmpnoaddr,
 +                                    http->getConn() != NULL ? http->getConn()->clientConnection->remote : tmpnoaddr,
                                      http->request,
                                      NULL,
+ #if USE_AUTH
                                      http->getConn() != NULL && http->getConn()->auth_user_request != NULL ?
                                      http->getConn()->auth_user_request : http->request->auth_user_request);
+ #else
+                                     NULL);
+ #endif
          node = (clientStreamNode *)http->client_stream.tail->data;
          clientStreamRead(node, http, node->readBuffer);
          return;
index 75895b896d51b1ebf3373aad99ee71065cf70f46,df9252fb409b753eaed5bcba8917ce7648f35cff..b1bf1be2acee7dfc7d25364f64ef333a4bca7017
@@@ -93,16 -93,8 +93,14 @@@ public
      _SQUID_INLINE_ StoreEntry *loggingEntry() const;
      void loggingEntry(StoreEntry *);
  
-     _SQUID_INLINE_ ConnStateData * getConn();
-     _SQUID_INLINE_ ConnStateData * const getConn() const;
+     _SQUID_INLINE_ ConnStateData * getConn() const;
      _SQUID_INLINE_ void setConn(ConnStateData *);
 +
 +    /** Details of the client socket which produced us.
 +     * Treat as read-only for the lifetime of this HTTP request.
 +     */
 +    Comm::ConnectionPointer clientConnection;
 +
      HttpRequest *request;             /* Parsed URL ... */
      char *uri;
      char *log_uri;
diff --cc src/comm.cc
index cc5dc0047407ebaa390fbf1b097cfc7cb625ce8d,b92dc8e92f1808174cafc85d1594641af30d124d..8e2ccfb8dd9e04ba6d6e3d6e241da928b21945b1
@@@ -99,14 -130,14 +99,7 @@@ static void commSetNoLinger(int)
  static void commSetTcpNoDelay(int);
  #endif
  static void commSetTcpRcvbuf(int, int);
 -static PF commConnectFree;
 -static IPH commConnectDnsHandle;
 -
 -typedef enum {
 -    COMM_CB_READ = 1,
 -    COMM_CB_DERIVED
 -} comm_callback_t;
  
- /*
- typedef enum {
-     COMM_CB_READ = 1,
-     COMM_CB_DERIVED
- } comm_callback_t;
- */
  static MemAllocator *conn_close_pool = NULL;
  fd_debug_t *fdd_table = NULL;
  
@@@ -578,12 -597,7 +562,12 @@@ comm_openex(int sock_type
          return -1;
      }
  
-     // temporary for the transition. comm_openex will eventually have a conn to play with.
 -    debugs(50, 3, "comm_openex: Opened socket FD " << new_socket << " : family=" << AI->ai_family << ", type=" << AI->ai_socktype << ", protocol=" << AI->ai_protocol );
++    // XXX: temporary for the transition. comm_openex will eventually have a conn to play with.
 +    Comm::ConnectionPointer conn = new Comm::Connection;
 +    conn->local = addr;
 +    conn->fd = new_socket;
 +
 +    debugs(50, 3, "comm_openex: Opened socket " << conn << " : family=" << AI->ai_family << ", type=" << AI->ai_socktype << ", protocol=" << AI->ai_protocol );
  
      /* set TOS if needed */
      if (tos)
  
      PROF_stop(comm_open);
  
-     // XXX transition only. prevent conn from closing the new FD on functio exit.
++    // XXX transition only. prevent conn from closing the new FD on function exit.
 +    conn->fd = -1;
      return new_socket;
  }
  
@@@ -621,22 -634,29 +605,24 @@@ comm_init_opened(const Comm::Connection
                   const char *note,
                   struct addrinfo *AI)
  {
 -    assert(new_socket >= 0);
 +    assert(Comm::IsConnOpen(conn));
      assert(AI);
  
 -    fde *F = NULL;
 -
      /* update fdstat */
 -    debugs(5, 5, "comm_open: FD " << new_socket << " is a new socket");
 -
 -    assert(!isOpen(new_socket));
 -    fd_open(new_socket, FD_SOCKET, note);
 -
 -    fdd_table[new_socket].close_file = NULL;
 -
 -    fdd_table[new_socket].close_line = 0;
 +    debugs(5, 5, HERE << conn << " is a new socket");
  
 -    F = &fd_table[new_socket];
 +    assert(!isOpen(conn->fd)); // NP: global isOpen checks the fde entry for openness not the Comm::Connection
 +    fd_open(conn->fd, FD_SOCKET, note);
  
 -    F->local_addr = addr;
 +    fdd_table[conn->fd].close_file = NULL;
 +    fdd_table[conn->fd].close_line = 0;
  
 +    fde *F = &fd_table[conn->fd];
 +    F->local_addr = conn->local;
      F->tosToServer = tos;
      F->nfmarkToServer = nfmark;
      F->sock_family = AI->ai_family;
  }
  
@@@ -741,51 -763,327 +727,23 @@@ comm_import_opened(const Comm::Connecti
       */
  }
  
- #if 0
 -
 -CBDATA_CLASS_INIT(ConnectStateData);
 -
 -void *
 -ConnectStateData::operator new (size_t size)
 -{
 -    CBDATA_INIT_TYPE(ConnectStateData);
 -    return cbdataAlloc(ConnectStateData);
 -}
 -
 -void
 -ConnectStateData::operator delete (void *address)
 -{
 -    cbdataFree(address);
 -}
 -
 -
 -
 -void
 -commConnectStart(int fd, const char *host, u_short port, AsyncCall::Pointer &cb)
 -{
 -    debugs(cb->debugSection, cb->debugLevel, "commConnectStart: FD " << fd <<
 -           ", cb " << cb << ", " << host << ":" << port); // TODO: just print *cb
 -
 -    ConnectStateData *cs;
 -    cs = new ConnectStateData;
 -    cs->fd = fd;
 -    cs->host = xstrdup(host);
 -    cs->default_port = port;
 -    cs->callback = cb;
 -
 -    comm_add_close_handler(fd, commConnectFree, cs);
 -    ipcache_nbgethostbyname(host, commConnectDnsHandle, cs);
 -}
 -
 -// TODO: Remove this and similar callback registration functions by replacing
 -// (callback,data) parameters with an AsyncCall so that we do not have to use
 -// a generic call name and debug level when creating an AsyncCall. This will
 -// also cut the number of callback registration routines in half.
 -void
 -commConnectStart(int fd, const char *host, u_short port, CNCB * callback, void *data)
 -{
 -    debugs(5, 5, "commConnectStart: FD " << fd << ", data " << data << ", " << host << ":" << port);
 -    AsyncCall::Pointer call = commCbCall(5,3,
 -                                         "SomeCommConnectHandler", CommConnectCbPtrFun(callback, data));
 -    commConnectStart(fd, host, port, call);
 -}
 -
 -static void
 -commConnectDnsHandle(const ipcache_addrs *ia, const DnsLookupDetails &details, void *data)
 -{
 -    ConnectStateData *cs = (ConnectStateData *)data;
 -    cs->dns = details;
 -
 -    if (ia == NULL) {
 -        debugs(5, 3, "commConnectDnsHandle: Unknown host: " << cs->host);
 -        cs->callCallback(COMM_ERR_DNS, 0);
 -        return;
 -    }
 -
 -    assert(ia->cur < ia->count);
 -
 -    cs->default_addr = ia->in_addrs[ia->cur];
 -
 -    if (Config.onoff.balance_on_multiple_ip)
 -        ipcacheCycleAddr(cs->host, NULL);
 -
 -    cs->addrcount = ia->count;
 -
 -    cs->connstart = squid_curtime;
 -
 -    cs->connect();
 -}
 -
 -void
 -ConnectStateData::callCallback(comm_err_t status, int xerrno)
 -{
 -    debugs(5, 3, "commConnectCallback: FD " << fd);
 -
 -    comm_remove_close_handler(fd, commConnectFree, this);
 -    commSetTimeout(fd, -1, NULL, NULL);
 -
 -    typedef CommConnectCbParams Params;
 -    Params &params = GetCommParams<Params>(callback);
 -    params.fd = fd;
 -    params.dns = dns;
 -    params.flag = status;
 -    params.xerrno = xerrno;
 -    ScheduleCallHere(callback);
 -    callback = NULL;
 -
 -    commConnectFree(fd, this);
 -}
 -
 -static void
 -commConnectFree(int fd, void *data)
 -{
 -    ConnectStateData *cs = (ConnectStateData *)data;
 -    debugs(5, 3, "commConnectFree: FD " << fd);
 -//    delete cs->callback;
 -    cs->callback = NULL;
 -    safe_free(cs->host);
 -    delete cs;
 -}
 -
 -static void
 -copyFDFlags(int to, fde *F)
 -{
 -    if (F->flags.close_on_exec)
 -        commSetCloseOnExec(to);
 -
 -    if (F->flags.nonblocking)
 -        commSetNonBlocking(to);
 -
 -#ifdef TCP_NODELAY
 -
 -    if (F->flags.nodelay)
 -        commSetTcpNoDelay(to);
 -
 -#endif
 -
 -    if (Config.tcpRcvBufsz > 0)
 -        commSetTcpRcvbuf(to, Config.tcpRcvBufsz);
 -}
 -
 -/* Reset FD so that we can connect() again */
--int
- commSetTimeout_old(int fd, int timeout, CTCB * handler, void *data)
 -ConnectStateData::commResetFD()
--{
-     debugs(5, 3, HERE << "FD " << fd << " timeout " << timeout);
-     assert(fd >= 0);
-     assert(fd < Squid_MaxFD);
 -
 -// XXX: do we have to check this?
 -//
 -//    if (!cbdataReferenceValid(callback.data))
 -//        return 0;
 -
 -    statCounter.syscalls.sock.sockets++;
 -
--    fde *F = &fd_table[fd];
-     assert(F->flags.open);
--
-     if (timeout < 0) {
-         cbdataReferenceDone(F->timeout_data);
-         F->timeout_handler = NULL;
-         F->timeout = 0;
-     } else {
-         if (handler) {
-             cbdataReferenceDone(F->timeout_data);
-             F->timeout_handler = handler;
-             F->timeout_data = cbdataReference(data);
-         }
 -    struct addrinfo *AI = NULL;
 -    F->local_addr.GetAddrInfo(AI);
 -    int new_family = AI->ai_family;
--
-         F->timeout = squid_curtime + (time_t) timeout;
 -    int fd2 = socket(new_family, AI->ai_socktype, AI->ai_protocol);
 -
 -    if (fd2 < 0) {
 -        debugs(5, DBG_CRITICAL, HERE << "WARNING: FD " << fd2 << " socket failed to allocate: " << xstrerror());
 -
 -        if (ENFILE == errno || EMFILE == errno)
 -            fdAdjustReserved();
 -
 -        F->local_addr.FreeAddrInfo(AI);
 -        return 0;
--    }
--
-     return F->timeout;
- }
 -#ifdef _SQUID_MSWIN_
 -
 -    /* On Windows dup2() can't work correctly on Sockets, the          */
 -    /* workaround is to close the destination Socket before call them. */
 -    close(fd);
 -
--#endif
 -
 -    if (dup2(fd2, fd) < 0) {
 -        debugs(5, DBG_CRITICAL, HERE << "WARNING: dup2(FD " << fd2 << ", FD " << fd << ") failed: " << xstrerror());
 -
 -        if (ENFILE == errno || EMFILE == errno)
 -            fdAdjustReserved();
 -
 -        close(fd2);
 -
 -        F->local_addr.FreeAddrInfo(AI);
 -        return 0;
 -    }
 -    Comm::ResetSelect(fd);
 -
 -    close(fd2);
 -
 -    debugs(50, 3, "commResetFD: Reset socket FD " << fd << "->" << fd2 << " : family=" << new_family );
 -
 -    /* INET6: copy the new sockets family type to the FDE table */
 -    F->sock_family = new_family;
 -
 -    F->flags.called_connect = 0;
 -
 -    /*
 -     * yuck, this has assumptions about comm_open() arguments for
 -     * the original socket
 -     */
 -
 -    /* MUST be done before binding or face OS Error: "(99) Cannot assign requested address"... */
 -    if ( F->flags.transparent ) {
 -        comm_set_transparent(fd);
 -    }
 -
 -    if (commBind(fd, *AI) != COMM_OK) {
 -        debugs(5, DBG_CRITICAL, "WARNING: Reset of FD " << fd << " for " << F->local_addr << " failed to bind: " << xstrerror());
 -        F->local_addr.FreeAddrInfo(AI);
 -        return 0;
 -    }
 -    F->local_addr.FreeAddrInfo(AI);
 -
 -    if (F->tosToServer)
 -        Ip::Qos::setSockTos(fd, F->tosToServer);
 -
 -    if (F->nfmarkToServer)
 -        Ip::Qos::setSockNfmark(fd, F->nfmarkToServer);
 -
 -    if ( Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && F->local_addr.IsIPv6() )
 -        comm_set_v6only(fd, 1);
 -
 -    copyFDFlags(fd, F);
 -
 -    return 1;
 -}
--
 +// Legacy pre-AsyncCalls API for FD timeouts.
  int
 -ConnectStateData::commRetryConnect()
 +commSetTimeout(int fd, int timeout, CTCB * handler, void *data)
  {
 -    assert(addrcount > 0);
 -
 -    if (addrcount == 1) {
 -        if (tries >= Config.retry.maxtries)
 -            return 0;
 -
 -        if (squid_curtime - connstart > Config.Timeout.connect)
 -            return 0;
 -    } else {
 -        if (tries > addrcount) {
 -            /* Flush bad address count in case we are
 -             * skipping over incompatible protocol
 -             */
 -            ipcacheMarkAllGood(host);
 -            return 0;
 -        }
 -    }
 -
 -    return commResetFD();
 -}
 -
 -static void
 -commReconnect(void *data)
 -{
 -    ConnectStateData *cs = (ConnectStateData *)data;
 -    ipcache_nbgethostbyname(cs->host, commConnectDnsHandle, cs);
 -}
 -
 -/** Connect SOCK to specified DEST_PORT at DEST_HOST. */
 -void
 -ConnectStateData::Connect(int fd, void *me)
 -{
 -    ConnectStateData *cs = (ConnectStateData *)me;
 -    assert (cs->fd == fd);
 -    cs->connect();
 -}
 -
 -void
 -ConnectStateData::defaults()
 -{
 -    S = default_addr;
 -    S.SetPort(default_port);
 +    AsyncCall::Pointer call;
 +    debugs(5, 3, HERE << "FD " << fd << " timeout " << timeout);
 +    if (handler != NULL)
 +        call=commCbCall(5,4, "SomeTimeoutHandler", CommTimeoutCbPtrFun(handler, data));
 +    else
 +        call = NULL;
 +    return commSetTimeout(fd, timeout, call);
  }
  
 -void
 -ConnectStateData::connect()
 -{
 -    defaults();
 -
 -    debugs(5,5, HERE << "to " << S);
 -
 -    switch (comm_connect_addr(fd, S) ) {
 -
 -    case COMM_INPROGRESS:
 -        debugs(5, 5, HERE << "FD " << fd << ": COMM_INPROGRESS");
 -        Comm::SetSelect(fd, COMM_SELECT_WRITE, ConnectStateData::Connect, this, 0);
 -        break;
 -
 -    case COMM_OK:
 -        debugs(5, 5, HERE << "FD " << fd << ": COMM_OK - connected");
 -        ipcacheMarkGoodAddr(host, S);
 -        callCallback(COMM_OK, 0);
 -        break;
 -
 -    case COMM_ERR_PROTOCOL:
 -        debugs(5, 5, HERE "FD " << fd << ": COMM_ERR_PROTOCOL - try again");
 -        /* problem using the desired protocol over this socket.
 -         * skip to the next address and hope it's more compatible
 -         * but do not mark the current address as bad
 -         */
 -        tries++;
 -        if (commRetryConnect()) {
 -            /* Force an addr cycle to move forward to the next possible address */
 -            ipcacheCycleAddr(host, NULL);
 -            eventAdd("commReconnect", commReconnect, this, this->addrcount == 1 ? 0.05 : 0.0, 0);
 -        } else {
 -            debugs(5, 5, HERE << "FD " << fd << ": COMM_ERR_PROTOCOL - ERR tried too many times already.");
 -            callCallback(COMM_ERR_CONNECT, errno);
 -        }
 -        break;
 -
 -    default:
 -        debugs(5, 5, HERE "FD " << fd << ": * - try again");
 -        tries++;
 -        ipcacheMarkBadAddr(host, S);
 -
 -#if USE_ICMP
 -        if (Config.onoff.test_reachability)
 -            netdbDeleteAddrNetwork(S);
 -#endif
 -
 -        if (commRetryConnect()) {
 -            eventAdd("commReconnect", commReconnect, this, this->addrcount == 1 ? 0.05 : 0.0, 0);
 -        } else {
 -            debugs(5, 5, HERE << "FD " << fd << ": * - ERR tried too many times already.");
 -            callCallback(COMM_ERR_CONNECT, errno);
 -        }
 -    }
 -}
 -/*
 +// Legacy pre-Comm::Connection API for FD timeouts
 +// still used by non-socket FD code dealing with pipes and IPC sockets.
  int
 -commSetTimeout_old(int fd, int timeout, PF * handler, void *data)
 +commSetTimeout(int fd, int timeout, AsyncCall::Pointer &callback)
  {
      debugs(5, 3, HERE << "FD " << fd << " timeout " << timeout);
      assert(fd >= 0);
@@@ -1063,22 -1367,9 +1021,22 @@@ comm_lingering_close(int fd
   * closed, TCP generates a RESET
   */
  void
 -comm_reset_close(int fd)
 +comm_reset_close(Comm::ConnectionPointer &conn)
  {
-         debugs(50, DBG_CRITICAL, "ERROR: Closing FD " << conn->fd << " with TCP RST: " << xstrerror());
 +    struct linger L;
 +    L.l_onoff = 1;
 +    L.l_linger = 0;
 +
 +    if (setsockopt(conn->fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0)
++        debugs(50, DBG_CRITICAL, "ERROR: Closing " << conn << " with TCP RST: " << xstrerror());
 +
 +    conn->close();
 +}
  
 +// Legacy close function.
 +void
 +old_comm_reset_close(int fd)
 +{
      struct linger L;
      L.l_onoff = 1;
      L.l_linger = 0;
Simple merge
index 7374b8f1ee5542c75f2d1044c2c95fd1b67d2c4b,0000000000000000000000000000000000000000..b3e952d9853065fd7001a755995a402fba13ff39
mode 100644,000000..100644
--- /dev/null
@@@ -1,327 -1,0 +1,326 @@@
- //#include "base/TextException.h"
 +/*
 + * DEBUG: section 05    Socket Connection Opener
 + */
 +
 +#include "config.h"
 +#include "comm/ConnOpener.h"
 +#include "comm/Connection.h"
 +#include "comm/Loops.h"
 +#include "comm.h"
 +#include "fde.h"
 +#include "icmp/net_db.h"
 +#include "SquidTime.h"
 +
 +namespace Comm {
 +    CBDATA_CLASS_INIT(ConnOpener);
 +};
 +
 +Comm::ConnOpener::ConnOpener(Comm::ConnectionPointer &c, AsyncCall::Pointer &handler, time_t ctimeout) :
 +        AsyncJob("Comm::ConnOpener"),
 +        host_(NULL),
 +        conn_(c),
 +        callback_(handler),
 +        totalTries_(0),
 +        failRetries_(0),
 +        connectTimeout_(ctimeout),
 +        connectStart_(0)
 +{}
 +
 +Comm::ConnOpener::~ConnOpener()
 +{
 +    safe_free(host_);
 +}
 +
 +bool
 +Comm::ConnOpener::doneAll() const
 +{
 +    // is the conn_ to be opened still waiting?
 +    if (conn_ == NULL) {
 +        return AsyncJob::doneAll();
 +    }
 +
 +    // is the callback still to be called?
 +    if (callback_ == NULL || callback_->canceled()) {
 +        return AsyncJob::doneAll();
 +    }
 +
 +    return false;
 +}
 +
 +void
 +Comm::ConnOpener::swanSong()
 +{
 +    // cancel any event watchers
 +    // done here to get the "swanSong" mention in cancel debugging.
 +    if (calls_.earlyAbort_ != NULL) {
 +        calls_.earlyAbort_->cancel("Comm::ConnOpener::swanSong");
 +        calls_.earlyAbort_ = NULL;
 +    }
 +    if (calls_.timeout_ != NULL) {
 +        calls_.timeout_->cancel("Comm::ConnOpener::swanSong");
 +        calls_.timeout_ = NULL;
 +    }
 +
 +    // rollback what we can from the job state
 +    if (conn_ != NULL && conn_->isOpen()) {
 +        // drop any handlers now to save a lot of cycles later
 +        Comm::SetSelect(conn_->fd, COMM_SELECT_WRITE, NULL, NULL, 0);
 +        commUnsetConnTimeout(conn_);
 +        // it never reached fully open, so abort the FD
 +        conn_->close();
 +    }
 +
 +    if (callback_ != NULL) {
 +        if (callback_->canceled())
 +            callback_ = NULL;
 +        else
 +            // inform the still-waiting caller we are dying
 +            doneConnecting(COMM_ERR_CONNECT, 0);
 +    }
 +
 +    AsyncJob::swanSong();
 +}
 +
 +void
 +Comm::ConnOpener::setHost(const char * new_host)
 +{
 +    // unset and erase if already set.
 +    if (host_ != NULL)
 +        safe_free(host_);
 +
 +    // set the new one if given.
 +    if (new_host != NULL)
 +        host_ = xstrdup(new_host);
 +}
 +
 +const char *
 +Comm::ConnOpener::getHost() const
 +{
 +    return host_;
 +}
 +
 +/**
 + * Connection attempt are completed. One way or the other.
 + * Pass the results back to the external handler.
 + * NP: on connection errors the connection close() must be called first.
 + */
 +void
 +Comm::ConnOpener::doneConnecting(comm_err_t status, int xerrno)
 +{
 +    // only mark the address good/bad AFTER connect is finished.
 +    if (host_ != NULL) {
 +        if (xerrno == 0)
 +            ipcacheMarkGoodAddr(host_, conn_->remote);
 +        else {
 +            ipcacheMarkBadAddr(host_, conn_->remote);
 +#if USE_ICMP
 +            if (Config.onoff.test_reachability)
 +                netdbDeleteAddrNetwork(conn_->remote);
 +#endif
 +        }
 +    }
 +
 +    if (callback_ != NULL) {
 +        typedef CommConnectCbParams Params;
 +        Params &params = GetCommParams<Params>(callback_);
 +        params.conn = conn_;
 +        params.flag = status;
 +        params.xerrno = xerrno;
 +        ScheduleCallHere(callback_);
 +        callback_ = NULL;
 +    }
 +
 +    /* ensure cleared local state, we are done. */
 +    conn_ = NULL;
 +}
 +
 +void
 +Comm::ConnOpener::start()
 +{
 +    Must(conn_ != NULL);
 +
 +    /* get a socket open ready for connecting with */
 +    if (!conn_->isOpen()) {
 +#if USE_IPV6
 +        /* outbound sockets have no need to be protocol agnostic. */
 +        if (conn_->remote.IsIPv4()) {
 +            conn_->local.SetIPv4();
 +        }
 +#endif
 +        conn_->fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, conn_->local, conn_->flags, conn_->tos, conn_->nfmark, host_);
 +        if (!conn_->isOpen()) {
 +            doneConnecting(COMM_ERR_CONNECT, 0);
 +            return;
 +        }
 +    }
 +
 +    typedef CommCbMemFunT<Comm::ConnOpener, CommConnectCbParams> abortDialer;
 +    calls_.earlyAbort_ = JobCallback(5, 4, abortDialer, this, Comm::ConnOpener::earlyAbort);
 +    comm_add_close_handler(conn_->fd, calls_.earlyAbort_);
 +
 +    typedef CommCbMemFunT<Comm::ConnOpener, CommTimeoutCbParams> timeoutDialer;
 +    calls_.timeout_ = JobCallback(5, 4, timeoutDialer, this, Comm::ConnOpener::timeout);
 +    debugs(5, 3, HERE << conn_ << " timeout " << connectTimeout_);
 +    commSetConnTimeout(conn_, connectTimeout_, calls_.timeout_);
 +
 +    connectStart_ = squid_curtime;
 +    connect();
 +}
 +
 +void
 +Comm::ConnOpener::connected()
 +{
 +    /*
 +     * stats.conn_open is used to account for the number of
 +     * connections that we have open to the peer, so we can limit
 +     * based on the max-conn option.  We need to increment here,
 +     * even if the connection may fail.
 +     */
 +    if (conn_->getPeer())
 +        conn_->getPeer()->stats.conn_open++;
 +
 +    lookupLocalAddress();
 +
 +    /* TODO: remove these fd_table accesses. But old code still depends on fd_table flags to
 +     *       indicate the state of a raw fd object being passed around.
 +     *       Also, legacy code still depends on comm_local_port() with no access to Comm::Connection
 +     *       when those are done comm_local_port can become one of our member functions to do the below.
 +     */
 +    fd_table[conn_->fd].flags.open = 1;
 +    fd_table[conn_->fd].local_addr = conn_->local;
 +}
 +
 +/** Make an FD connection attempt.
 + * Handles the case(s) when a partially setup connection gets closed early.
 + */
 +void
 +Comm::ConnOpener::connect()
 +{
 +    Must(conn_ != NULL);
 +
 +    // our parent Jobs signal abort by cancelling their callbacks.
 +    if (callback_ == NULL || callback_->canceled())
 +        return;
 +
 +    totalTries_++;
 +
 +    switch (comm_connect_addr(conn_->fd, conn_->remote) ) {
 +
 +    case COMM_INPROGRESS:
 +        // check for timeout FIRST.
 +        if (squid_curtime - connectStart_ > connectTimeout_) {
 +            debugs(5, 5, HERE << conn_ << ": * - ERR took too long already.");
 +            calls_.earlyAbort_->cancel("Comm::ConnOpener::connect timed out");
 +            calls_.earlyAbort_ = NULL;
 +            conn_->close();
 +            doneConnecting(COMM_TIMEOUT, errno);
 +            return;
 +        } else {
 +            debugs(5, 5, HERE << conn_ << ": COMM_INPROGRESS");
 +            Comm::SetSelect(conn_->fd, COMM_SELECT_WRITE, Comm::ConnOpener::InProgressConnectRetry, this, 0);
 +        }
 +        break;
 +
 +    case COMM_OK:
 +        debugs(5, 5, HERE << conn_ << ": COMM_OK - connected");
 +        connected();
 +        doneConnecting(COMM_OK, 0);
 +        break;
 +
 +    default:
 +        failRetries_++;
 +
 +        // check for timeout FIRST.
 +        if(squid_curtime - connectStart_ > connectTimeout_) {
 +            debugs(5, 5, HERE << conn_ << ": * - ERR took too long to receive response.");
 +            calls_.earlyAbort_->cancel("Comm::ConnOpener::connect timed out");
 +            calls_.earlyAbort_ = NULL;
 +            conn_->close();
 +            doneConnecting(COMM_TIMEOUT, errno);
 +        } else if (failRetries_ < Config.connect_retries) {
 +            debugs(5, 5, HERE << conn_ << ": * - try again");
 +            eventAdd("Comm::ConnOpener::DelayedConnectRetry", Comm::ConnOpener::DelayedConnectRetry, this, 0.05, 0);
 +            return;
 +        } else {
 +            // send ERROR back to the upper layer.
 +            debugs(5, 5, HERE << conn_ << ": * - ERR tried too many times already.");
 +            calls_.earlyAbort_->cancel("Comm::ConnOpener::connect failed");
 +            calls_.earlyAbort_ = NULL;
 +            conn_->close();
 +            doneConnecting(COMM_ERR_CONNECT, errno);
 +        }
 +    }
 +}
 +
 +/**
 + * Lookup local-end address and port of the TCP link just opened.
 + * This ensure the connection local details are set correctly
 + */
 +void
 +Comm::ConnOpener::lookupLocalAddress()
 +{
 +    struct addrinfo *addr = NULL;
 +    conn_->local.InitAddrInfo(addr);
 +
 +    if (getsockname(conn_->fd, addr->ai_addr, &(addr->ai_addrlen)) != 0) {
 +        debugs(50, DBG_IMPORTANT, "ERROR: Failed to retrieve TCP/UDP details for socket: " << conn_ << ": " << xstrerror());
 +        conn_->local.FreeAddrInfo(addr);
 +        return;
 +    }
 +
 +    conn_->local = *addr;
 +    conn_->local.FreeAddrInfo(addr);
 +    debugs(5, 6, HERE << conn_);
 +}
 +
 +/** Abort connection attempt.
 + * Handles the case(s) when a partially setup connection gets closed early.
 + */
 +void
 +Comm::ConnOpener::earlyAbort(const CommConnectCbParams &io)
 +{
 +    debugs(5, 3, HERE << io.conn);
 +    doneConnecting(COMM_ERR_CLOSING, io.xerrno); // NP: is closing or shutdown better?
 +}
 +
 +/**
 + * Handles the case(s) when a partially setup connection gets timed out.
 + * NP: When commSetConnTimeout accepts generic CommCommonCbParams this can die.
 + */
 +void
 +Comm::ConnOpener::timeout(const CommTimeoutCbParams &)
 +{
 +    connect();
 +}
 +
 +/* Legacy Wrapper for the retry event after COMM_INPROGRESS
 + * XXX: As soon as Comm::SetSelect() accepts Async calls we can use a ConnOpener::connect call
 + */
 +void
 +Comm::ConnOpener::InProgressConnectRetry(int fd, void *data)
 +{
 +    ConnOpener *cs = static_cast<Comm::ConnOpener *>(data);
 +    assert(cs);
 +
 +    // Ew. we are now outside the all AsyncJob protections.
 +    // get back inside by scheduling another call...
 +    typedef NullaryMemFunT<Comm::ConnOpener> Dialer;
 +    AsyncCall::Pointer call = JobCallback(5, 4, Dialer, cs, Comm::ConnOpener::connect);
 +    ScheduleCallHere(call);
 +}
 +
 +/* Legacy Wrapper for the retry event with small delay after errors.
 + * XXX: As soon as eventAdd() accepts Async calls we can use a ConnOpener::connect call
 + */
 +void
 +Comm::ConnOpener::DelayedConnectRetry(void *data)
 +{
 +    ConnOpener *cs = static_cast<Comm::ConnOpener *>(data);
 +    assert(cs);
 +
 +    // Ew. we are now outside the all AsyncJob protections.
 +    // get back inside by scheduling another call...
 +    typedef NullaryMemFunT<Comm::ConnOpener> Dialer;
 +    AsyncCall::Pointer call = JobCallback(5, 4, Dialer, cs, Comm::ConnOpener::connect);
 +    ScheduleCallHere(call);
 +}
index a862cd5426bd2b1a13b4ac7e9f679aac96282c9a,4026737754f8837cfe4e1ab8e09d7f860e976ed0..c8806e28dad19e69bbe9e256727634cbec264c4e
@@@ -16,9 -15,9 +16,7 @@@ Comm::CallbackTableInit(
      iocb_table = static_cast<CbEntry*>(xcalloc(Squid_MaxFD, sizeof(CbEntry)));
      for (int pos = 0; pos < Squid_MaxFD; pos++) {
          iocb_table[pos].fd = pos;
- //        iocb_table[pos].readcb.fd = pos;
 -        iocb_table[pos].readcb.fd = pos;
          iocb_table[pos].readcb.type = IOCB_READ;
- //        iocb_table[pos].writecb.fd = pos;
 -        iocb_table[pos].writecb.fd = pos;
          iocb_table[pos].writecb.type = IOCB_WRITE;
      }
  }
index 0ba83c14adc334dd91ba6896ec3d8f542f91407a,cdb8f5032a8dcbf072fd4e0c1edaa524de3ea9d3..2ed340dc9d03a589997b9fae7bb9de5ee950653b
@@@ -27,3 -23,3 +27,5 @@@ libcomm_la_SOURCES= 
        Write.h \
        \
        comm_internal.h
++
++EXTRA_DIST= stub_libcomm.cc
index 095d0b56e4df65894639843f08e6676ff5d20335,d4a884d1e03a5c9d4a9ab232d748d2df07477567..2f31d99a1627e099026ad030bf143d86fc0b62a7
  #if USE_POLL
  
  #include "squid.h"
++#include "comm/Connection.h"
  #include "comm/Loops.h"
  #include "fde.h"
++#include "ICP.h"
  #include "mgr/Registration.h"
  #include "SquidTime.h"
  #include "Store.h"
@@@ -166,10 -166,10 +168,10 @@@ Comm::ResetSelect(int fd
  static int
  fdIsIcp(int fd)
  {
--    if (fd == theInIcpConnection)
++    if (icpIncomingConn != NULL && icpIncomingConn->fd == fd)
          return 1;
  
--    if (fd == theOutIcpConnection)
++    if (icpOutgoingConn != NULL && icpOutgoingConn->fd == fd)
          return 1;
  
      return 0;
@@@ -279,12 -279,12 +281,11 @@@ comm_poll_icp_incoming(void
      int nevents;
      icp_io_events = 0;
  
--    if (theInIcpConnection >= 0)
--        fds[nfds++] = theInIcpConnection;
++    if (Comm::IsConnOpen(icpIncomingConn))
++        fds[nfds++] = icpIncomingConn->fd;
  
--    if (theInIcpConnection != theOutIcpConnection)
--        if (theOutIcpConnection >= 0)
--            fds[nfds++] = theOutIcpConnection;
++    if (icpIncomingConn != icpOutgoingConn && Comm::IsConnOpen(icpOutgoingConn))
++            fds[nfds++] = icpOutgoingConn->fd;
  
      if (nfds == 0)
          return;
index a32b47bbc019bcd83e30872f5ba216e2774a9ef8,a32b47bbc019bcd83e30872f5ba216e2774a9ef8..d7c773393cde4bdfb0ce2a6a6447c600bfab13b9
@@@ -35,7 -35,7 +35,9 @@@
  #if USE_SELECT
  
  #include "squid.h"
++#include "comm/Connection.h"
  #include "comm/Loops.h"
++#include "ICP.h"
  #include "mgr/Registration.h"
  #include "SquidTime.h"
  #include "Store.h"
@@@ -163,10 -163,10 +165,10 @@@ Comm::ResetSelect(int fd
  static int
  fdIsIcp(int fd)
  {
--    if (fd == theInIcpConnection)
++    if (icpIncomingConn != NULL && fd == icpIncomingConn->fd)
          return 1;
  
--    if (fd == theOutIcpConnection)
++    if (icpOutgoingConn != NULL && fd == icpOutgoingConn->fd)
          return 1;
  
      return 0;
@@@ -273,12 -273,12 +275,11 @@@ comm_select_icp_incoming(void
      int nevents;
      icp_io_events = 0;
  
--    if (theInIcpConnection >= 0)
--        fds[nfds++] = theInIcpConnection;
++    if (Comm::IsConnOpen(icpIncomingConn))
++        fds[nfds++] = icpIncomingConn->fd;
  
--    if (theInIcpConnection != theOutIcpConnection)
--        if (theOutIcpConnection >= 0)
--            fds[nfds++] = theOutIcpConnection;
++    if (Comm::IsConnOpen(icpOutgoingConn) && icpIncomingConn != icpOutgoingConn)
++        fds[nfds++] = icpOutgoingConn->fd;
  
      if (nfds == 0)
          return;
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..16a80a30dbda3c5979d257da644d8f34a032ae18
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,60 @@@
++#include "config.h"
++#include "base/AsyncJob.h"
++#include "structs.h"
++
++#define STUB_API "comm/libcomm.la"
++#include "tests/STUB.h"
++
++#include "AcceptLimiter.h"
++Comm::AcceptLimiter dummy;
++Comm::AcceptLimiter & Comm::AcceptLimiter::Instance() STUB_RETVAL(dummy)
++void Comm::AcceptLimiter::defer(Comm::TcpAcceptor *afd) STUB
++void Comm::AcceptLimiter::removeDead(const Comm::TcpAcceptor *afd) STUB
++void Comm::AcceptLimiter::kick() STUB
++
++#include "comm/Connection.h"
++Comm::Connection::Connection() STUB
++Comm::Connection::~Connection() STUB
++Comm::ConnectionPointer Comm::Connection::copyDetails() const STUB_RETVAL(NULL)
++void Comm::Connection::close() STUB
++peer * const Comm::Connection::getPeer() const STUB_RETVAL(NULL)
++void Comm::Connection::setPeer(peer * p) STUB
++
++#include "comm/ConnOpener.h"
++bool Comm::ConnOpener::doneAll() const STUB_RETVAL(false)
++//Comm::ConnOpener::ConnOpener(Comm::ConnectionPointer &, AsyncCall::Pointer &, time_t) STUB
++//Comm::ConnOpener::~ConnOpener() STUB
++void Comm::ConnOpener::setHost(const char *) STUB
++const char * Comm::ConnOpener::getHost() const STUB_RETVAL(NULL)
++
++#include "comm/forward.h"
++bool Comm::IsConnOpen(const Comm::ConnectionPointer &) STUB_RETVAL(false)
++
++#include "comm/IoCallback.h"
++void Comm::IoCallback::setCallback(iocb_type type, AsyncCall::Pointer &cb, char *buf, FREE *func, int sz) STUB
++void Comm::IoCallback::selectOrQueueWrite() STUB
++void Comm::IoCallback::cancel(const char *reason) STUB
++void Comm::IoCallback::finish(comm_err_t code, int xerrn) STUB
++Comm::CbEntry *Comm::iocb_table = NULL;
++void Comm::CallbackTableInit() STUB
++void Comm::CallbackTableDestruct() STUB
++
++#include "comm/Loops.h"
++void Comm::SelectLoopInit(void) STUB
++void Comm::SetSelect(int, unsigned int, PF *, void *, time_t) STUB
++void Comm::ResetSelect(int) STUB
++comm_err_t Comm::DoSelect(int) STUB_RETVAL(COMM_ERROR)
++void Comm::QuickPollRequired(void) STUB
++
++#include "comm/TcpAcceptor.h"
++//Comm::TcpAcceptor(const Comm::ConnectionPointer &conn, const char *note, const Subscription::Pointer &aSub) STUB
++void Comm::TcpAcceptor::subscribe(const Subscription::Pointer &aSub) STUB
++void Comm::TcpAcceptor::unsubscribe(const char *) STUB
++void Comm::TcpAcceptor::acceptNext() STUB
++void Comm::TcpAcceptor::notify(const comm_err_t flag, const Comm::ConnectionPointer &) const STUB
++
++#include "comm/Write.h"
++void Comm::Write(const Comm::ConnectionPointer &, const char *, int, AsyncCall::Pointer &, FREE *) STUB
++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 Comm::HandleWrite STUB
diff --cc src/defines.h
index afc977ddd06a687e2db2514956822ba576962abe,f7b283726dcc1b8fcb4c365e4afe879ee0b9a754..40936b532486f804b898743a83df8bebcc557b06
  #define COMM_SELECT_READ   (0x1)
  #define COMM_SELECT_WRITE  (0x2)
  
- /*
--#define COMM_NONBLOCKING      0x01
--#define COMM_NOCLOEXEC                0x02
--#define COMM_REUSEADDR                0x04
--#define COMM_TRANSPARENT      0x08
--#define COMM_DOBIND           0x10
- */
--
  #define DISK_OK                   (0)
  #define DISK_ERROR               (-1)
  #define DISK_EOF                 (-2)
index 566291e8168b2c4ec5e7203544bccc2eeae54965,566291e8168b2c4ec5e7203544bccc2eeae54965..586b4da6b2758bc312747f871459386a2aaff769
@@@ -65,6 -65,6 +65,7 @@@
  #include "DelayUser.h"
  #include "DelayTagged.h"
  #include "ip/Address.h"
++#include "comm/Connection.h"
  
  /// \ingroup DelayPoolsInternal
  long DelayPools::MemoryUsed = 0;
index c0df7f66bc5e447d88bd041f642ecca97da428f8,6d8a67474fe01a621e64d814a0c646c4baa1c12a..e329a9d2776b3b7bafe99bada4726d741473a462
@@@ -33,9 -33,6 +33,8 @@@
   */
  
  #include "squid.h"
- #include "base/InstanceId.h"
 +#include "comm/Connection.h"
 +#include "comm/ConnOpener.h"
  #include "comm.h"
  #include "comm/Loops.h"
  #include "comm/Write.h"
@@@ -234,11 -232,8 +234,11 @@@ static void idnsParseWIN32SearchList(co
  #endif
  static void idnsCacheQuery(idns_query * q);
  static void idnsSendQuery(idns_query * q);
+ static IOCB idnsReadVCHeader;
  static void idnsDoSendQueryVC(nsvc *vc);
- static IOCB idnsReadVCHeader;
 +static CNCB idnsInitVCConnected;
 +static IOCB idnsReadVC;
 +static IOCB idnsSentQueryVC;
  
  static int idnsFromKnownNameserver(Ip::Address const &from);
  static idns_query *idnsFindQuery(unsigned short id);
@@@ -772,8 -766,11 +773,12 @@@ idnsDoSendQueryVC(nsvc *vc
  
      vc->busy = 1;
  
-     commSetConnTimeout(vc->conn, Config.Timeout.idns_query, nil);
+     // Comm needs seconds but idnsCheckQueue() will check the exact timeout
+     const int timeout = (Config.Timeout.idns_query % 1000 ?
+                          Config.Timeout.idns_query + 1000 : Config.Timeout.idns_query) / 1000;
 +    AsyncCall::Pointer nil;
 -    commSetTimeout(vc->fd, timeout, NULL, NULL);
++    commSetConnTimeout(vc->conn, timeout, nil);
  
      AsyncCall::Pointer call = commCbCall(78, 5, "idnsSentQueryVC",
                                           CommIoCbPtrFun(&idnsSentQueryVC, vc));
index 3a42e3ab10c559dce2d402e095cc787b28df485d,8c8308b80217ad84a91b6b84d9e76cfe50fed1e4..fabedb95ffb1ca3b691e69a0ea305956406a4b65
   *
   */
  #include "config.h"
- #include "auth/UserRequest.h"
 +#include "comm/Connection.h"
  #include "comm/Write.h"
- #include "err_detail_type.h"
  #include "errorpage.h"
- #include "fde.h"
+ #if USE_AUTH
+ #include "auth/UserRequest.h"
+ #endif
+ #include "SquidTime.h"
+ #include "Store.h"
  #include "html_quote.h"
  #include "HttpReply.h"
  #include "HttpRequest.h"
@@@ -504,8 -506,9 +507,9 @@@ errorSend(const Comm::ConnectionPointe
      MemBuf *mb = rep->pack();
      AsyncCall::Pointer call = commCbCall(78, 5, "errorSendComplete",
                                           CommIoCbPtrFun(&errorSendComplete, err));
 -    Comm::Write(fd, mb, call);
 +    Comm::Write(conn, mb, call);
      delete mb;
      delete rep;
  }
  
diff --cc src/errorpage.h
index c50887a072c998f18f3f8f6672b946054893b038,bd7a52dae7a475f55c6a0ab226818e17b6f2eab1..07c424879d2c1d2315d3e2fc8dfe3f76fd76c399
  #define   SQUID_ERRORPAGE_H
  
  #include "squid.h"
+ #if USE_AUTH
  #include "auth/UserRequest.h"
+ #endif
  #include "cbdata.h"
 +#include "comm/forward.h"
  #include "ip/Address.h"
  #if USE_SSL
  #include "ssl/ErrorDetail.h"
@@@ -201,16 -204,16 +205,16 @@@ SQUIDCEXTERN void errorClean(void)
   * err to the cbdata because comm_write() requires it
   * for all callback data pointers.
   *
-  \note normally errorSend() should only be called from
-  *       routines in ssl.c and pass.c, where we don't have any
-  *       StoreEntry's.  In client_side.c we must allocate a StoreEntry
-  *       for errors and use errorAppendEntry() to account for
-  *       persistent/pipeline connections.
+  \note normally errorSend() should only be called from
+  *     routines in ssl.c and pass.c, where we don't have any
+  *     StoreEntry's.  In client_side.c we must allocate a StoreEntry
+  *     for errors and use errorAppendEntry() to account for
+  *     persistent/pipeline connections.
   *
-  * \param clientConn  socket where page object is to be written
-  * \param err         This object is destroyed after use in this function.
 - \param fd      socket where page object is to be written
 - \param err     This object is destroyed after use in this function.
++ \param clientConn  socket where page object is to be written
++ \param err         This object is destroyed after use in this function.
   */
 -SQUIDCEXTERN void errorSend(int fd, ErrorState *err);
 +SQUIDCEXTERN void errorSend(const Comm::ConnectionPointer &conn, ErrorState *err);
  
  /**
   \ingroup ErrorPageAPI
diff --cc src/esi/Esi.cc
index 7f0cceb10cf153d2c085bebfbfcf5196e0ea94e3,7f0cceb10cf153d2c085bebfbfcf5196e0ea94e3..fefca431e68d6840cf3df60e37e4643f4fde8b94
@@@ -41,6 -41,6 +41,7 @@@
  #include "esi/Esi.h"
  #include "clientStream.h"
  #include "client_side_request.h"
++#include "comm/Connection.h"
  #include "errorpage.h"
  #include "esi/Segment.h"
  #include "esi/Element.h"
@@@ -1459,7 -1459,7 +1460,8 @@@ ESIContext::fail (
      /* don't honour range requests - for errors we send it all */
      flags.error = 1;
      /* create an error object */
--    ErrorState * err = clientBuildError(errorpage, errorstatus, NULL, http->getConn()->peer, http->request);
++    // 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);
      err->err_msg = errormessage;
      errormessage = NULL;
      rep = err->BuildHttpReply();
index 72e4909be1021190eb73ee48ba0235d5adff8018,b64cda26a9d76a95641429c5f9e8be99a8810709..b65518f0f7eadb6e913f352a378e5c9ed628ed22
@@@ -157,12 -156,12 +156,12 @@@ Eui::Eui48::encode(char *buf, const in
  
  // return binary representation of the EUI
  bool
 -Eui::Eui48::lookup(Ip::Address &c)
 +Eui::Eui48::lookup(const Ip::Address &c)
  {
      struct arpreq arpReq;
- #if !_SQUID_WIN32_
+ #if !_SQUID_WINDOWS_
      struct sockaddr_in *sa = NULL;
- #endif /* !_SQUID_WIN32_ */
+ #endif /* !_SQUID_WINDOWS_ */
  
      Ip::Address ipAddr = c;
      ipAddr.SetPort(0);
index d5aab6cb18c8297ee627ceb1e23723bfee96783e,c661e5de7f9cd1b48f6fbd20ad54b7765cbc3e1a..a52a4ef7f16a426b5f79e5747ac4036bf1c66dfc
  #endif
  #include "ip/tools.h"
  #include "client_side.h"
 +#include "comm/Connection.h"
  #include "HttpRequest.h"
  #include "HttpReply.h"
- #include "auth/Acl.h"
- #include "auth/Gadgets.h"
  #include "helper.h"
  #include "MemBuf.h"
  #include "rfc1738.h"
diff --cc src/forward.cc
index c6f60222962e6d75f64392b6d6a8fd5fbbdeaf6f,d5b29626be13e3937b2f555ff03f908be14d039f..05d7a73498672e55d5c612b0fbe8c29d76544b1b
@@@ -250,11 -251,11 +250,11 @@@ FwdState::fwdStart(const Comm::Connecti
          internalStart(request, entry);
          return;
  
-     case PROTO_CACHEOBJ:
+     case AnyP::PROTO_CACHE_OBJECT:
 -        CacheManager::GetInstance()->Start(client_fd, request, entry);
 +        CacheManager::GetInstance()->Start(clientConn, request, entry);
          return;
  
-     case PROTO_URN:
+     case AnyP::PROTO_URN:
          urnStart(request, entry);
          return;
  
@@@ -384,15 -361,13 +384,6 @@@ fwdServerClosedWrapper(int fd, void *da
      fwd->serverClosed(fd);
  }
  
- #if 0
--static void
--fwdConnectStartWrapper(void *data)
--{
--    FwdState *fwd = (FwdState *) data;
--    fwd->connectStart();
--}
- #endif
--
  #if USE_SSL
  static void
  fwdNegotiateSSLWrapper(int fd, void *data)
      FwdState *fwd = (FwdState *) data;
      fwd->negotiateSSL(fd);
  }
  #endif
  
 -static void
 -fwdConnectDoneWrapper(int server_fd, const DnsLookupDetails &dns, comm_err_t status, int xerrno, void *data)
 -{
 -    FwdState *fwd = (FwdState *) data;
 -    fwd->connectDone(server_fd, dns, status, xerrno);
 -}
 -
 -static void
 -fwdConnectTimeoutWrapper(int fd, void *data)
 +void
 +fwdConnectDoneWrapper(const Comm::ConnectionPointer &conn, comm_err_t status, int xerrno, void *data)
  {
      FwdState *fwd = (FwdState *) data;
 -    fwd->connectTimeout(fd);
 -}
 -
 -/*
 - * Accounts for closed persistent connections
 - */
 -static void
 -fwdPeerClosed(int fd, void *data)
 -{
 -    peer *p = (peer *)data;
 -    p->stats.conn_open--;
 +    fwd->connectDone(conn, status, xerrno);
  }
  
  /**** PRIVATE *****************************************************************/
@@@ -511,27 -507,39 +503,28 @@@ voi
  FwdState::retryOrBail()
  {
      if (checkRetry()) {
 -        int originserver = (servers->_peer == NULL);
 -        debugs(17, 3, "fwdServerClosed: re-forwarding (" << n_tries << " tries, " << (squid_curtime - start_t) << " secs)");
 -
 -        if (servers->next) {
 -            /* use next, or cycle if origin server isn't last */
 -            FwdServer *fs = servers;
 -            FwdServer **T, *T2 = NULL;
 -            servers = fs->next;
 -
 -            for (T = &servers; *T; T2 = *T, T = &(*T)->next);
 -            if (T2 && T2->_peer) {
 -                /* cycle */
 -                *T = fs;
 -                fs->next = NULL;
 -            } else {
 -                /* Use next. The last "direct" entry is retried multiple times */
 -                servers = fs->next;
 -                fwdServerFree(fs);
 -                originserver = 0;
 +        debugs(17, 3, HERE << "re-forwarding (" << n_tries << " tries, " << (squid_curtime - start_t) << " secs)");
 +
 +        serverDestinations.shift(); // last one failed. try another.
 +
 +        if (serverDestinations.size() > 0) {
 +            /* Ditch error page if it was created before.
 +             * A new one will be created if there's another problem */
 +            if (err) {
 +                errorStateFree(err);
 +                err = NULL;
              }
 -        }
  
 -        /* Ditch error page if it was created before.
 -         * A new one will be created if there's another problem */
 -        if (err) {
 -            errorStateFree(err);
 -            err = NULL;
 +            connectStart();
 +            return;
          }
 +        // else bail. no more serverDestinations possible to try.
  
-         // AYJ: cannot-forward error ??
- // is this hack needed since we now have doneWithRetries() below?
- //        ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
- //        errorAppendEntry(entry, anErr);
 -        /* use eventAdd to break potential call sequence loops and to slow things down a little */
 -        eventAdd("fwdConnectStart", fwdConnectStartWrapper, this, originserver ? 0.05 : 0.005, 0);
 -
 -        return;
++        // produce cannot-forward error, but only if no more specific one exists
++        if (!err) {
++            ErrorState *anErr = errorCon(ERR_CANNOT_FORWARD, HTTP_INTERNAL_SERVER_ERROR, request);
++            errorAppendEntry(entry, anErr);
++        }
      }
  
      // TODO: should we call completed() here and move doneWithRetries there?
@@@ -692,49 -707,63 +689,49 @@@ FwdState::initiateSSL(
  #endif
  
  void
 -FwdState::connectDone(int aServerFD, const DnsLookupDetails &dns, comm_err_t status, int xerrno)
 +FwdState::connectDone(const Comm::ConnectionPointer &conn, comm_err_t status, int xerrno)
  {
 -    FwdServer *fs = servers;
 -    assert(server_fd == aServerFD);
 -
 -    request->recordLookup(dns);
 -
 -    if (Config.onoff.log_ip_on_direct && status != COMM_ERR_DNS && fs->code == HIER_DIRECT)
 -        updateHierarchyInfo();
 -
 -    if (status == COMM_ERR_DNS) {
 -        /*
 -         * Only set the dont_retry flag if the DNS lookup fails on
 -         * a direct connection.  If DNS lookup fails when trying
 -         * a neighbor cache, we may want to retry another option.
 -         */
 -
 -        if (NULL == fs->_peer)
 -            flags.dont_retry = 1;
 +    if (status != COMM_OK) {
 +        ErrorState *const anErr = makeConnectingError(ERR_CONNECT_FAIL);
 +        anErr->xerrno = xerrno;
 +        fail(anErr);
  
 -        debugs(17, 4, "fwdConnectDone: Unknown host: " << request->GetHost());
 +        /* it might have been a timeout with a partially open link */
 +        if (conn != NULL) {
 +            if (conn->getPeer())
 +                peerConnectFailed(conn->getPeer());
  
 -        ErrorState *const anErr = makeConnectingError(ERR_DNS_FAIL);
 +            conn->close();
 +        }
 +        retryOrBail();
 +        return;
 +    }
  
 -        anErr->dnsError = dns.error;
 +    serverConn = conn;
  
 -        fail(anErr);
 +#if REDUNDANT_NOW
 +    if (Config.onoff.log_ip_on_direct && serverConnection()->peerType == HIER_DIRECT)
 +        updateHierarchyInfo();
 +#endif
  
 -        comm_close(server_fd);
 -    } else if (status != COMM_OK) {
 -        assert(fs);
 -        ErrorState *const anErr = makeConnectingError(ERR_CONNECT_FAIL);
 -        anErr->xerrno = xerrno;
 +    debugs(17, 3, HERE << serverConnection() << ": '" << entry->url() << "'" );
  
 -        fail(anErr);
 +    comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
  
 -        if (fs->_peer)
 -            peerConnectFailed(fs->_peer);
 +    if (serverConnection()->getPeer())
 +        peerConnectSucceded(serverConnection()->getPeer());
  
 -        comm_close(server_fd);
 -    } else {
 -        debugs(17, 3, "fwdConnectDone: FD " << server_fd << ": '" << entry->url() << "'" );
 -
 -        if (fs->_peer)
 -            peerConnectSucceded(fs->_peer);
 +    updateHierarchyInfo();
  
  #if USE_SSL
 -
 -        if ((fs->_peer && fs->_peer->use_ssl) ||
 -                (!fs->_peer && request->protocol == AnyP::PROTO_HTTPS)) {
 -            initiateSSL();
 -            return;
 -        }
 -
 -#endif
 -        dispatch();
 +    if ((serverConnection()->getPeer() && serverConnection()->getPeer()->use_ssl) ||
-             (!serverConnection()->getPeer() && request->protocol == PROTO_HTTPS)) {
++            (!serverConnection()->getPeer() && request->protocol == AnyP::PROTO_HTTPS)) {
 +        initiateSSL();
 +        return;
      }
 +#endif
 +
 +    dispatch();
  }
  
  void
@@@ -794,17 -832,25 +791,24 @@@ FwdState::connectStart(
      if (ftimeout < ctimeout)
          ctimeout = ftimeout;
  
 -    if (fs->_peer && request->flags.sslBumped == true) {
++    if (serverDestinations[0]->getPeer() && request->flags.sslBumped == true) {
+         debugs(50, 4, "fwdConnectStart: Ssl bumped connections through parrent proxy are not allowed");
+         ErrorState *anErr = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, request);
+         fail(anErr);
+         self = NULL; // refcounted
+         return;
+     }
      request->flags.pinned = 0;
 -    if (fs->code == PINNED) {
 +    if (serverDestinations[0]->peerType == PINNED) {
          ConnStateData *pinned_connection = request->pinnedConnection();
          assert(pinned_connection);
 -        fd = pinned_connection->validatePinnedConnection(request, fs->_peer);
 -        if (fd >= 0) {
 +        serverConn = pinned_connection->validatePinnedConnection(request, serverDestinations[0]->getPeer());
 +        if (Comm::IsConnOpen(serverConn)) {
-             pinned_connection->unpinConnection(); // XXX: this should be just remove the pinning close handler ??
  #if 0
 -            if (!fs->_peer)
 -                fs->code = HIER_DIRECT;
 +            if (!serverConn->getPeer())
 +                serverConn->peerType = HIER_DIRECT;
  #endif
 -            server_fd = fd;
              n_tries++;
              request->flags.pinned = 1;
              if (pinned_connection->pinnedAuth())
              return;
          }
          /* Failure. Fall back on next path */
-         debugs(17, 2, HERE << " Pinned connection " << pinned_connection << " not valid. Releasing.");
-         request->releasePinnedConnection();
+         debugs(17,2,HERE << " Pinned connection " << pinned_connection << " not valid.");
 -        servers = fs->next;
 -        fwdServerFree(fs);
 -        connectStart();
 +        serverDestinations.shift();
 +        startConnectionOrFail();
          return;
      }
  
      entry->mem_obj->checkUrlChecksum();
  #endif
  
 -    outgoing = getOutgoingAddr(request, fs->_peer);
 -
 -    // if IPv6 is disabled try to force IPv4-only outgoing.
 -    if (!Ip::EnableIpv6 && !outgoing.SetIPv4()) {
 -        debugs(50, 4, "fwdConnectStart: IPv6 is Disabled. Cannot connect from " << outgoing);
 -        ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
 -        anErr->xerrno = EAFNOSUPPORT;
 -        fail(anErr);
 -        self = NULL;  // refcounted
 -        return;
 -    }
 -
 -    // if IPv6 is split-stack, prefer IPv4
 -    if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK) {
 -        // NP: This is not a great choice of default,
 -        // but with the current Internet being IPv4-majority has a higher success rate.
 -        // if setting to IPv4 fails we dont care, that just means to use IPv6 outgoing.
 -        outgoing.SetIPv4();
 +    /* Get the server side TOS and Netfilter mark to be set on the connection. */
 +    if (Ip::Qos::TheConfig.isAclTosActive()) {
 +        serverDestinations[0]->tos = GetTosToServer(request);
      }
- #if SO_MARK
 -
 -    tos_t tos = GetTosToServer(request);
 -
+ #if SO_MARK && USE_LIBCAP
 -    nfmark_t mark = GetNfmarkToServer(request);
 -    debugs(17, 3, "fwdConnectStart: got outgoing addr " << outgoing << ", tos " << int(tos)
 -           << ", netfilter mark " << mark);
 +    serverDestinations[0]->nfmark = GetNfmarkToServer(request);
 +    debugs(17, 3, "fwdConnectStart: got outgoing addr " << serverDestinations[0]->local << ", tos " << int(serverDestinations[0]->tos)
 +           << ", netfilter mark " << serverDestinations[0]->nfmark);
  #else
 -    nfmark_t mark = 0;
 -    debugs(17, 3, "fwdConnectStart: got outgoing addr " << outgoing << ", tos " << int(tos));
 +    serverDestinations[0]->nfmark = 0;
 +    debugs(17, 3, "fwdConnectStart: got outgoing addr " << serverDestinations[0]->local << ", tos " << int(serverDestinations[0]->tos));
  #endif
  
 -    int commFlags = COMM_NONBLOCKING;
 -    if (request->flags.spoof_client_ip) {
 -        if (!fs->_peer || !fs->_peer->options.no_tproxy)
 -            commFlags |= COMM_TRANSPARENT;
 -        // else no tproxy today ...
 -    }
 -
 -    fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, outgoing, commFlags, tos, mark, url);
 -
 -    debugs(17, 3, "fwdConnectStart: got TCP FD " << fd);
 -
 -    if (fd < 0) {
 -        debugs(50, 4, "fwdConnectStart: " << xstrerror());
 -        ErrorState *anErr = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request);
 -        anErr->xerrno = errno;
 -        fail(anErr);
 -        self = NULL;  // refcounted
 -        return;
 -    }
 -
 -    server_fd = fd;
 -    n_tries++;
 -
 -    if (!fs->_peer)
 -        origin_tries++;
 -
 -    if (comm_local_port(fd))
 -        request->hier.peer_local_addr = fd_table[fd].local_addr;
 -
 -    /*
 -     * stats.conn_open is used to account for the number of
 -     * connections that we have open to the peer, so we can limit
 -     * based on the max-conn option.  We need to increment here,
 -     * even if the connection may fail.
 -     */
 -
 -    if (fs->_peer) {
 -        fs->_peer->stats.conn_open++;
 -        comm_add_close_handler(fd, fwdPeerClosed, fs->_peer);
 -    }
 -
 -    comm_add_close_handler(fd, fwdServerClosedWrapper, this);
 -
 -    commSetTimeout(fd, ctimeout, fwdConnectTimeoutWrapper, this);
 -
 -    updateHierarchyInfo();
 -    commConnectStart(fd, host, port, fwdConnectDoneWrapper, this);
 -}
 -
 -void
 -FwdState::startComplete(FwdServer * theServers)
 -{
 -    debugs(17, 3, "fwdStartComplete: " << entry->url()  );
 -
 -    if (theServers != NULL) {
 -        servers = theServers;
 -        connectStart();
 -    } else {
 -        startFail();
 -    }
 -}
 -
 -void
 -FwdState::startFail()
 -{
 -    debugs(17, 3, "fwdStartFail: " << entry->url()  );
 -    ErrorState *anErr = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, request);
 -    anErr->xerrno = errno;
 -    fail(anErr);
 -    self = NULL;      // refcounted
 +    calls.connector = commCbCall(17,3, "fwdConnectDoneWrapper", CommConnectCbPtrFun(fwdConnectDoneWrapper, this));
 +    Comm::ConnOpener *cs = new Comm::ConnOpener(serverDestinations[0], calls.connector, ctimeout);
 +    cs->setHost(host);
 +    AsyncJob::Start(cs);
  }
  
  void
@@@ -1175,25 -1331,26 +1178,23 @@@ FwdState::updateHierarchyInfo(
  {
      assert(request);
  
 -    FwdServer *fs = servers;
 -    assert(fs);
 +    assert(serverDestinations.size() > 0);
  
 -    const char *nextHop = NULL;
 +    char nextHop[256];
  
 -    if (fs->_peer) {
 +    if (serverConnection()->getPeer()) {
          // went to peer, log peer host name
 -        nextHop = fs->_peer->name;
 +        snprintf(nextHop,256,"%s", serverConnection()->getPeer()->name);
      } else {
          // went DIRECT, must honor log_ip_on_direct
 -
 -        // XXX: or should we use request->host_addr here? how?
 -        assert(server_fd >= 0);
 -        nextHop = fd_table[server_fd].ipaddr;
 -        if (!Config.onoff.log_ip_on_direct || !nextHop[0])
 -            nextHop = request->GetHost(); // domain name
 +        if (!Config.onoff.log_ip_on_direct)
 +            snprintf(nextHop,256,"%s",request->GetHost()); // domain name
 +        else
 +            serverConnection()->remote.NtoA(nextHop, 256);
      }
  
-     request->hier.peer_local_port = serverConnection()->local.GetPort();
 -    assert(nextHop);
 -    hierarchyNote(&request->hier, fs->code, nextHop);
 +    assert(nextHop[0]);
 +    hierarchyNote(&request->hier, serverConnection()->peerType, nextHop);
  }
  
  
@@@ -1275,21 -1443,9 +1276,20 @@@ getOutgoingAddress(HttpRequest * reques
          ch.my_addr = request->my_addr;
      }
  
 -    return aclMapAddr(Config.accessList.outgoing_address, &ch);
 +    acl_address *l;
 +    for (l = Config.accessList.outgoing_address; l; l = l->next) {
 +
 +        /* check if the outgoing address is usable to the destination */
 +        if (conn->remote.IsIPv4() != l->addr.IsIPv4()) continue;
 +
 +        /* check ACLs for this outgoing address */
 +        if (!l->aclList || ch.matchAclListFast(l->aclList)) {
 +            conn->local = l->addr;
 +            return;
 +        }
 +    }
  }
  
- // XXX: convert this to accepting a serverConn and migrate to QosConfig.cc
  tos_t
  GetTosToServer(HttpRequest * request)
  {
diff --cc src/ftp.cc
index d6a55fb29c6d7737bbfa497330560cf7cd1a8bc8,5858e024d3a161ea79c03a9d9c6888c54f663a2e..f0579736d43634ed19e44961eb03bb8b240f6ed6
@@@ -1584,11 -1578,13 +1584,13 @@@ FtpStateData::writeCommand(const char *
          ebuf = xstrdup(buf);
  
      safe_free(ctrl.last_command);
      safe_free(ctrl.last_reply);
      ctrl.last_command = ebuf;
  
 -    if (!canSend(ctrl.fd)) {
 -        debugs(9, 2, HERE << "cannot send to closing ctrl FD " << ctrl.fd);
 +    if (!Comm::IsConnOpen(ctrl.conn)) {
 +        debugs(9, 2, HERE << "cannot send to closing ctrl " << ctrl.conn);
          // TODO: assert(ctrl.closer != NULL);
          return;
      }
@@@ -1775,10 -1777,8 +1777,8 @@@ void FtpStateData::ftpReadControlReply(
              scheduleReadControlReply(0);
          } else {
              failed(ERR_READ_ERROR, io.xerrno);
 -            /* failed closes ctrl.fd and frees ftpState */
 +            /* failed closes ctrl.conn and frees ftpState */
-             return;
          }
          return;
      }
  
diff --cc src/globals.h
Simple merge
diff --cc src/gopher.cc
index 7f112e729463f0cf61ac633ad347854866513701,fa78bf26e6478302a92c7a37fbbf19deaf997361..605074e80aaeee05643c1d65fe4b7a11cbf00db7
@@@ -810,9 -807,12 +807,13 @@@ gopherReadReply(const Comm::ConnectionP
  
          kb_incr(&statCounter.server.all.kbytes_in, len);
          kb_incr(&statCounter.server.other.kbytes_in, len);
+     }
  
 -    debugs(10, 5, "gopherReadReply: FD " << fd << " read len=" << len);
++    debugs(10, 5, HERE << conn << " read len=" << len);
+     if (flag == COMM_OK && len > 0) {
 -        commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
 +        AsyncCall::Pointer nil;
 +        commSetConnTimeout(conn, Config.Timeout.read, nil);
          IOStats.Gopher.reads++;
  
          for (clen = len - 1, bin = 0; clen; bin++)
          debugs(50, 1, "gopherReadReply: error reading: " << xstrerror());
  
          if (ignoreErrno(errno)) {
-             do_next_read = 1;
 -            comm_read(fd, buf, read_sz, gopherReadReply, gopherState);
++            AsyncCall::Pointer call = commCbCall(5,4, "gopherReadReply",
++                                                 CommIoCbPtrFun(gopherReadReply, gopherState));
++            comm_read(conn, buf, read_sz, call);
          } else {
-             ErrorState *err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, gopherState->fwd->request);
+             ErrorState *err;
+             err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, gopherState->fwd->request);
              err->xerrno = errno;
              gopherState->fwd->fail(err);
 -            comm_close(fd);
 +            gopherState->serverConn->close();
-             do_next_read = 0;
          }
      } else if (len == 0 && entry->isEmpty()) {
          gopherState->fwd->fail(errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE, gopherState->fwd->request));
 -        comm_close(fd);
 +        gopherState->serverConn->close();
-         do_next_read = 0;
      } else if (len == 0) {
          /* Connection closed; retrieval done. */
          /* flush the rest of data in temp buf if there is one. */
          entry->timestampsSet();
          entry->flush();
          gopherState->fwd->complete();
 -        comm_close(fd);
 +        gopherState->serverConn->close();
-         do_next_read = 0;
      } else {
          if (gopherState->conversion != gopher_ds::NORMAL) {
              gopherToHTML(gopherState, buf, len);
          } else {
              entry->append(buf, len);
          }
-         do_next_read = 1;
-     }
-     if (do_next_read) {
 -        comm_read(fd, buf, read_sz, gopherReadReply, gopherState);
 +        AsyncCall::Pointer call = commCbCall(5,4, "gopherReadReply",
 +                                             CommIoCbPtrFun(gopherReadReply, gopherState));
 +        comm_read(conn, buf, read_sz, call);
      }
-     return;
  }
  
  /**
diff --cc src/helper.cc
index c3165f02b4b846949e5f877cbf720bb7a821103e,fe129889a670134a7fa9cd6cbfb57e63b0261ec5..9099fd9fe79b28bdb69870b0feb3be86ad1a80aa
@@@ -862,11 -862,8 +862,8 @@@ helperHandleRead(const Comm::Connection
  
      debugs(84, 5, "helperHandleRead: " << len << " bytes from " << hlp->id_name << " #" << srv->index + 1);
  
-     if (flag != COMM_OK || len <= 0) {
-         if (len < 0)
-             debugs(84, 1, "helperHandleRead: FD " << conn->fd << " read: " << xstrerror());
+     if (flag != COMM_OK || len == 0) {
 -        comm_close(fd);
 +        srv->closePipesSafely();
          return;
      }
  
          srv->rbuf[0] = '\0';
      }
  
-     if (hlp->return_full_reply) {
-         debugs(84, 3, HERE << "Return entire buffer");
-         helperReturnBuffer(0, srv, hlp, srv->rbuf, srv->rbuf + srv->roffset);
-     } else {
-         while ((t = strchr(srv->rbuf, '\n'))) {
-             /* end of reply found */
-             char *msg = srv->rbuf;
-             int i = 0;
-             debugs(84, 3, "helperHandleRead: end of reply found");
-             if (t > srv->rbuf && t[-1] == '\r')
-                 t[-1] = '\0';
+     while ((t = strchr(srv->rbuf, hlp->eom))) {
+         /* end of reply found */
+         char *msg = srv->rbuf;
+         int i = 0;
+         debugs(84, 3, "helperHandleRead: end of reply found");
  
-             *t++ = '\0';
+         if (t > srv->rbuf && t[-1] == '\r' && hlp->eom == '\n')
+             t[-1] = '\0';
  
-             if (hlp->childs.concurrency) {
-                 i = strtol(msg, &msg, 10);
+         *t++ = '\0';
  
-                 while (*msg && xisspace(*msg))
-                     msg++;
-             }
+         if (hlp->childs.concurrency) {
+             i = strtol(msg, &msg, 10);
  
-             helperReturnBuffer(i, srv, hlp, msg, t);
+             while (*msg && xisspace(*msg))
+                 msg++;
          }
+         helperReturnBuffer(i, srv, hlp, msg, t);
      }
  
 -    if (srv->rfd != -1)
 -        comm_read(fd, srv->rbuf + srv->roffset, srv->rbuf_sz - srv->roffset - 1, helperHandleRead, srv);
 +    if (Comm::IsConnOpen(srv->readPipe)) {
 +        AsyncCall::Pointer call = commCbCall(5,4, "helperHandleRead",
 +                                             CommIoCbPtrFun(helperHandleRead, srv));
 +        comm_read(srv->readPipe, srv->rbuf + srv->roffset, srv->rbuf_sz - srv->roffset - 1, call);
 +    }
  }
  
  static void
@@@ -938,11 -927,8 +930,8 @@@ helperStatefulHandleRead(const Comm::Co
             hlp->id_name << " #" << srv->index + 1);
  
  
-     if (flag != COMM_OK || len <= 0) {
-         if (len < 0)
-             debugs(84, 1, "helperStatefulHandleRead: FD " << conn->fd << " read: " << xstrerror());
+     if (flag != COMM_OK || len == 0) {
 -        comm_close(fd);
 +        srv->closePipesSafely();
          return;
      }
  
diff --cc src/helper.h
index 7ebb2ba13d49cd5bdd0cad033cad11cb4014f454,a5dac223256e33e2203dc4c5d259e5eb29bbe4d3..7d40becbce8a46d9f0a01968a9fe74a1cb19a572
@@@ -35,9 -35,8 +35,9 @@@
  
  #include "squid.h"
  #include "cbdata.h"
- #include "HelperChildConfig.h"
 +#include "comm/forward.h"
  #include "ip/Address.h"
+ #include "HelperChildConfig.h"
  
  class helper_request;
  
diff --cc src/htcp.cc
Simple merge
diff --cc src/http.cc
index dd46bbb22658a007ff74fb24f60d8aea268bcae0,17bbbc30037f902cb1c8d76abee0dd1310781b7f..fc0b4b8538ca6ead970b2abf31262c2ced77ea3c
@@@ -90,9 -92,9 +93,9 @@@ HttpStateData::HttpStateData(FwdState *
      debugs(11,5,HERE << "HttpStateData " << this << " created");
      ignoreCacheControl = false;
      surrogateNoStore = false;
 -    fd = fwd->server_fd;
 +    serverConnection = fwd->serverConnection();
      readBuf = new MemBuf;
-     readBuf->init();
+     readBuf->init(16*1024, 256*1024);
      orig_request = HTTPMSGLOCK(fwd->request);
  
      // reset peer response time stats for %<pt
@@@ -1081,11 -1082,11 +1084,9 @@@ HttpStateData::readReply(const CommIoCb
      int clen;
      int len = io.size;
  
- //    assert(serverConnection->fd == io.fd); // XXX: false when closing. serverConnection-> will already be -1.
 -    assert(fd == io.fd);
--
      flags.do_next_read = 0;
  
 -    debugs(11, 5, "httpReadReply: FD " << fd << ": len " << len << ".");
 +    debugs(11, 5, HERE << io.conn << ": len " << len << ".");
  
      // Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us
      if (io.flag == COMM_ERR_CLOSING) {
              err->xerrno = io.xerrno;
              fwd->fail(err);
              flags.do_next_read = 0;
 -            comm_close(fd);
 +            serverConnection->close();
          }
          return;
      }
  
@@@ -2294,10 -2310,14 +2305,14 @@@ HttpStateData::handleRequestBodyProduce
  {
      ServerStateData::handleRequestBodyProducerAborted();
      if (entry->isEmpty()) {
 -        debugs(11, 3, "request body aborted: FD " << fd);
 +        debugs(11, 3, "request body aborted: " << serverConnection);
          ErrorState *err;
-         err = errorCon(ERR_READ_ERROR, HTTP_BAD_GATEWAY, fwd->request);
-         err->xerrno = errno;
+         // We usually get here when ICAP REQMOD aborts during body processing.
+         // We might also get here if client-side aborts, but then our response
+         // should not matter because either client-side will provide its own or
+         // there will be no response at all (e.g., if the the client has left).
+         err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, fwd->request);
+         err->xerrno = ERR_DETAIL_SRV_REQMOD_REQ_BODY;
          fwd->fail(err);
      }
  
diff --cc src/icp_v2.cc
index 2c6549adcc95c2bdb25b6e819bc828387d914618,990d72e0ecc711cd3a72a2911a52af1717e32569..2f0aa72daa073260ec172835604d495305e26ce9
   */
  
  #include "squid.h"
- #include "AccessLogEntry.h"
- #include "acl/Acl.h"
- #include "acl/FilledChecklist.h"
+ #include "Store.h"
  #include "comm.h"
  #include "comm/Loops.h"
+ #include "ICP.h"
 +#include "comm/Connection.h"
  #include "HttpRequest.h"
+ #include "acl/FilledChecklist.h"
+ #include "acl/Acl.h"
+ #include "AccessLogEntry.h"
+ #include "wordlist.h"
+ #include "SquidTime.h"
+ #include "SwapDir.h"
  #include "icmp/net_db.h"
- #include "ICP.h"
  #include "ip/Address.h"
  #include "ip/tools.h"
  #include "ipc/StartListening.h"
@@@ -677,7 -664,10 +677,10 @@@ icpHandleUdp(int sock, void *data
  
          icp_version = (int) buf[1];   /* cheat! */
  
-         if (icp_version == ICP_VERSION_2)
 -        if (theOutICPAddr == from)
++        if (icpOutgoingConn->local == from)
+             // ignore ICP packets which loop back (multicast usually)
+             debugs(12, 4, "icpHandleUdp: Ignoring UDP packet sent by myself");
+         else if (icp_version == ICP_VERSION_2)
              icpHandleIcpV2(sock, from, buf, len);
          else if (icp_version == ICP_VERSION_3)
              icpHandleIcpV3(sock, from, buf, len);
index d0d25fc0d7adc77cce96d635a2e7444841b73181,602ce2226186d73b0005e0193a7b9d286836d72b..3a9837d861396ae40ef2f54f044c9d16507af243
@@@ -145,42 -149,51 +145,42 @@@ Ip::Intercept::NetfilterTransparent(con
      /* Trust the user configured properly. If not no harm done.
       * We will simply attempt a bind outgoing on our own IP.
       */
 -    if (fd_table[fd].flags.transparent) {
 -        client.SetPort(0); // allow random outgoing port to prevent address clashes
 -        debugs(89, 5, HERE << "address TPROXY: me= " << me << ", client= " << client);
 -        return 0;
 -    }
 -
 -    debugs(89, 9, HERE << "address: me= " << me << ", client= " << client);
 +    newConn->remote.SetPort(0); // allow random outgoing port to prevent address clashes
 +    debugs(89, 5, HERE << "address TPROXY: " << newConn);
 +    return true;
 +#else
 +    return false;
  #endif
 -    return -1;
  }
  
 -int
 -Ip::Intercept::IpfwInterception(int fd, const Ip::Address &me, Ip::Address &dst, int silent)
 +bool
 +Ip::Intercept::IpfwInterception(const Comm::ConnectionPointer &newConn, int silent)
  {
  #if IPFW_TRANSPARENT
-     struct sockaddr_in lookup;
-     socklen_t len = sizeof(struct sockaddr_in);
-     newConn->local.GetSockAddr(lookup);
 -    struct addrinfo *lookup = NULL;
 -
 -    dst.GetAddrInfo(lookup,AF_INET);
++    struct sockaddr_storage lookup;
++    socklen_t len = sizeof(struct sockaddr_storage);
++    newConn->local.GetSockAddr(lookup, AF_INET);
  
      /** \par
       * Try lookup for IPFW interception. */
-     if ( getsockname(newConn->fd, &lookup, &len) != 0 ) {
 -    if ( getsockname(fd, lookup->ai_addr, &lookup->ai_addrlen) != 0 ) {
++    if ( getsockname(newConn->fd, (struct sockaddr*)&lookup, &len) != 0 ) {
          if ( !silent ) {
              debugs(89, DBG_IMPORTANT, HERE << " IPFW getsockname(...) failed: " << xstrerror());
 -            last_reported = squid_curtime;
 +            lastReported_ = squid_curtime;
          }
 +        debugs(89, 9, HERE << "address: " << newConn);
 +        return false;
      } else {
 -        dst = *lookup;
 +        newConn->local = lookup;
 +        debugs(89, 5, HERE << "address NAT: " << newConn);
 +        return true;
      }
 -
 -    Address::FreeAddrInfo(lookup);
 -
 -    if (me != dst) {
 -        debugs(89, 5, HERE << "address NAT: me= " << me << ", dst= " << dst);
 -        return 0;
 -    }
 -
 -    debugs(89, 9, HERE << "address: me= " << me << ", dst= " << dst);
  #endif
 -    return -1;
 +    return false;
  }
  
 -int
 -Ip::Intercept::IpfInterception(int fd, const Ip::Address &me, Ip::Address &client, Ip::Address &dst, int silent)
 +bool
 +Ip::Intercept::IpfInterception(const Comm::ConnectionPointer &newConn, int silent)
  {
  #if IPF_TRANSPARENT  /* --enable-ipf-transparent */
  
diff --cc src/ip/Qos.cci
index b52a99dd3f2ff3e32ad1fee6cf6af0a07c8f984c,11b5f362ba3c42a447ef119ed074c403025dd5bf..7d7c4a9e35edc3793c579d4dd665f9b996538f28
@@@ -16,16 -15,19 +16,19 @@@ Ip::Qos::setSockTos(const Comm::Connect
  }
  
  int
 -Ip::Qos::setSockNfmark(int fd, nfmark_t mark)
 +Ip::Qos::setSockNfmark(const Comm::ConnectionPointer &conn, nfmark_t mark)
  {
- #if SO_MARK
+ #if SO_MARK && USE_LIBCAP
 -    int x = setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(nfmark_t));
 +    int x = setsockopt(conn->fd, SOL_SOCKET, SO_MARK, &mark, sizeof(nfmark_t));
      if (x < 0)
 -        debugs(50, 2, "setSockNfmark: setsockopt(SO_MARK) on FD " << fd << ": " << xstrerror());
 +        debugs(50, 2, "setSockNfmark: setsockopt(SO_MARK) on " << conn << ": " << xstrerror());
      return x;
- #else
+ #elif USE_LIBCAP
      debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(SO_MARK) not supported on this platform");
      return -1;
+ #else
+     debugs(50, DBG_IMPORTANT, "WARNING: Netfilter marking disabled (netfilter marking requires build with LIBCAP)");
+     return -1;
  #endif
  }
  
Simple merge
index 9bab7cc3ce1c0ba4150248d82a3f53f4533e4468,02656fee3ded565fa7c8438e98a56a87a82d9a30..c6948c6aa62ff1aff15529526a417b4881a68df5
@@@ -11,9 -10,7 +11,8 @@@
  #include "base/TextException.h"
  #include "CacheManager.h"
  #include "comm.h"
 +#include "comm/Connection.h"
  #include "ipc/Coordinator.h"
- #include "ipc/FdNotes.h"
  #include "ipc/SharedListen.h"
  #include "mgr/Inquirer.h"
  #include "mgr/Request.h"
@@@ -134,7 -154,29 +156,29 @@@ Ipc::Coordinator::handleCacheMgrRespons
      Mgr::Inquirer::HandleRemoteAck(response);
  }
  
 -int
+ #if SQUID_SNMP
+ void
+ Ipc::Coordinator::handleSnmpRequest(const Snmp::Request& request)
+ {
+     debugs(54, 4, HERE);
+     Snmp::Response response(request.requestId);
+     TypedMsgHdr message;
+     response.pack(message);
+     SendMessage(MakeAddr(strandAddrPfx, request.requestorId), message);
+     AsyncJob::Start(new Snmp::Inquirer(request, strands_));
+ }
+ void
+ Ipc::Coordinator::handleSnmpResponse(const Snmp::Response& response)
+ {
+     debugs(54, 4, HERE);
+     Snmp::Inquirer::HandleRemoteAck(response);
+ }
+ #endif
 +Comm::ConnectionPointer
  Ipc::Coordinator::openListenSocket(const SharedListenRequest& request,
                                     int &errNo)
  {
index 3937cd387f1df9e1834cb6d03ff31e36189e4a8d,bc0d8fd765de6c647101ee28d374aab725f38f24..d81a04fe4bb6ba57c5d2472490c48f06a424793b
@@@ -46,9 -48,12 +48,12 @@@ protected
      void handleSharedListenRequest(const SharedListenRequest& request);
      void handleCacheMgrRequest(const Mgr::Request& request);
      void handleCacheMgrResponse(const Mgr::Response& response);
+ #if SQUID_SNMP
+     void handleSnmpRequest(const Snmp::Request& request);
+     void handleSnmpResponse(const Snmp::Response& response);
+ #endif
      /// calls comm_open_listener()
 -    int openListenSocket(const SharedListenRequest& request, int &errNo);
 +    Comm::ConnectionPointer openListenSocket(const SharedListenRequest& request, int &errNo);
  
  private:
      StrandCoords strands_; ///< registered processes and threads
index 0000000000000000000000000000000000000000,3650229a2d83da85910e24b56982c9d1eceef1b5..0d1de0f916d52ee9bdb71887fbe15f087a2dbd61
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,177 +1,180 @@@
+ /*
+  * $Id$
+  *
+  * DEBUG: section 54    Interprocess Communication
+  *
+  */
+ #include "config.h"
+ #include "base/AsyncJobCalls.h"
+ #include "base/TextException.h"
++#include "errorpage.h"
++#include "HttpReply.h"
++#include "HttpRequest.h"
+ #include "ipc/Forwarder.h"
+ #include "ipc/Port.h"
+ #include "ipc/TypedMsgHdr.h"
+ CBDATA_NAMESPACED_CLASS_INIT(Ipc, Forwarder);
+ Ipc::Forwarder::RequestsMap Ipc::Forwarder::TheRequestsMap;
+ unsigned int Ipc::Forwarder::LastRequestId = 0;
+ Ipc::Forwarder::Forwarder(Request::Pointer aRequest, double aTimeout):
+         AsyncJob("Ipc::Forwarder"),
+         request(aRequest), timeout(aTimeout)
+ {
+     debugs(54, 5, HERE);
+ }
+ Ipc::Forwarder::~Forwarder()
+ {
+     debugs(54, 5, HERE);
+     Must(request->requestId == 0);
+     cleanup();
+ }
+ /// perform cleanup actions
+ void
+ Ipc::Forwarder::cleanup()
+ {
+ }
+ void
+ Ipc::Forwarder::start()
+ {
+     debugs(54, 3, HERE);
+     typedef NullaryMemFunT<Forwarder> Dialer;
+     AsyncCall::Pointer callback = JobCallback(54, 5, Dialer, this, Forwarder::handleRemoteAck);
+     if (++LastRequestId == 0) // don't use zero value as request->requestId
+         ++LastRequestId;
+     request->requestId = LastRequestId;
+     TheRequestsMap[request->requestId] = callback;
+     TypedMsgHdr message;
+     try {
+         request->pack(message);
+     } catch (...) {
+         // assume the pack() call failed because the message did not fit
+         // TODO: add a more specific exception?
+         handleError();
+     }
+     SendMessage(coordinatorAddr, message);
+     eventAdd("Ipc::Forwarder::requestTimedOut", &Forwarder::RequestTimedOut,
+              this, timeout, 0, false);
+ }
+ void
+ Ipc::Forwarder::swanSong()
+ {
+     debugs(54, 5, HERE);
+     removeTimeoutEvent();
+     if (request->requestId > 0) {
+         DequeueRequest(request->requestId);
+         request->requestId = 0;
+     }
+     cleanup();
+ }
+ bool
+ Ipc::Forwarder::doneAll() const
+ {
+     debugs(54, 5, HERE);
+     return request->requestId == 0;
+ }
+ /// called when Coordinator starts processing the request
+ void
+ Ipc::Forwarder::handleRemoteAck()
+ {
+     debugs(54, 3, HERE);
+     request->requestId = 0;
+ }
+ /// Ipc::Forwarder::requestTimedOut wrapper
+ void
+ Ipc::Forwarder::RequestTimedOut(void* param)
+ {
+     debugs(54, 3, HERE);
+     Must(param != NULL);
+     Forwarder* fwdr = static_cast<Forwarder*>(param);
+     // use async call to enable job call protection that time events lack
+     CallJobHere(54, 5, fwdr, Forwarder, requestTimedOut);
+ }
+ /// called when Coordinator fails to start processing the request [in time]
+ void
+ Ipc::Forwarder::requestTimedOut()
+ {
+     debugs(54, 3, HERE);
+     handleTimeout();
+ }
+ void
+ Ipc::Forwarder::handleError()
+ {
+     mustStop("error");
+ }
+ void
+ Ipc::Forwarder::handleTimeout()
+ {
+     mustStop("timeout");
+ }
+ /// terminate with an error
+ void
+ Ipc::Forwarder::handleException(const std::exception& e)
+ {
+     debugs(54, 3, HERE << e.what());
+     mustStop("exception");
+ }
+ void
+ Ipc::Forwarder::callException(const std::exception& e)
+ {
+     try {
+         handleException(e);
+     } catch (const std::exception& ex) {
+         debugs(54, DBG_CRITICAL, HERE << ex.what());
+     }
+     AsyncJob::callException(e);
+ }
+ /// returns and forgets the right Forwarder callback for the request
+ AsyncCall::Pointer
+ Ipc::Forwarder::DequeueRequest(unsigned int requestId)
+ {
+     debugs(54, 3, HERE);
+     Must(requestId != 0);
+     AsyncCall::Pointer call;
+     RequestsMap::iterator request = TheRequestsMap.find(requestId);
+     if (request != TheRequestsMap.end()) {
+         call = request->second;
+         Must(call != NULL);
+         TheRequestsMap.erase(request);
+     }
+     return call;
+ }
+ /// called when we are no longer waiting for Coordinator to respond
+ void
+ Ipc::Forwarder::removeTimeoutEvent()
+ {
+     if (eventFind(&Forwarder::RequestTimedOut, this))
+         eventDelete(&Forwarder::RequestTimedOut, this);
+ }
+ void
+ Ipc::Forwarder::HandleRemoteAck(unsigned int requestId)
+ {
+     debugs(54, 3, HERE);
+     Must(requestId != 0);
+     AsyncCall::Pointer call = DequeueRequest(requestId);
+     if (call != NULL)
+         ScheduleCallHere(call);
+ }
index 0000000000000000000000000000000000000000,25b115b02022373ae5db0acd3c599360fbd13bce..dfda91f6e77a11ed5bb241fb012a3b3d20e1688a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,68 +1,69 @@@
+ /*
+  * $Id$
+  *
+  * DEBUG: section 54    Interprocess Communication
+  *
+  */
+ #ifndef SQUID_IPC_FORWARDER_H
+ #define SQUID_IPC_FORWARDER_H
+ #include "base/AsyncJob.h"
++#include "mgr/ActionParams.h"
+ #include "ipc/Request.h"
+ #include <map>
+ namespace Ipc
+ {
+ /** Forwards a worker request to coordinator.
+  * Waits for an ACK from Coordinator
+  * Send the data unit with an error response if forwarding fails.
+  */
+ class Forwarder: public AsyncJob
+ {
+ public:
+     Forwarder(Request::Pointer aRequest, double aTimeout);
+     virtual ~Forwarder();
+     /// finds and calls the right Forwarder upon Coordinator's response
+     static void HandleRemoteAck(unsigned int requestId);
+     /* has-to-be-public AsyncJob API */
+     virtual void callException(const std::exception& e);
+ protected:
+     /* AsyncJob API */
+     virtual void start();
+     virtual void swanSong();
+     virtual bool doneAll() const;
+     virtual void cleanup(); ///< perform cleanup actions
+     virtual void handleError();
+     virtual void handleTimeout();
+     virtual void handleException(const std::exception& e);
+     virtual void handleRemoteAck();
+ private:
+     static void RequestTimedOut(void* param);
+     void requestTimedOut();
+     void removeTimeoutEvent();
+     static AsyncCall::Pointer DequeueRequest(unsigned int requestId);
+ protected:
+     Request::Pointer request;
+     const double timeout; ///< response wait timeout in seconds
+     /// maps request->id to Forwarder::handleRemoteAck callback
+     typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
+     static RequestsMap TheRequestsMap; ///< pending Coordinator requests
+     static unsigned int LastRequestId; ///< last requestId used
+     CBDATA_CLASS2(Forwarder);
+ };
+ } // namespace Ipc
+ #endif /* SQUID_IPC_FORWARDER_H */
index 0000000000000000000000000000000000000000,d80dce5e3ad0adc40ac2bd2b2f436482534f6825..22c03a2d6af106ffe780c4421fc0fbdbd2f4634f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,206 +1,207 @@@
+ /*
+  * $Id$
+  *
+  * DEBUG: section 54    Interprocess Communication
+  *
+  */
+ #include "config.h"
+ #include "base/TextException.h"
++#include "comm.h"
+ #include "comm/Write.h"
+ #include "ipc/Inquirer.h"
+ #include "ipc/Port.h"
+ #include "ipc/TypedMsgHdr.h"
+ #include "MemBuf.h"
+ #include <algorithm>
+ CBDATA_NAMESPACED_CLASS_INIT(Ipc, Inquirer);
+ Ipc::Inquirer::RequestsMap Ipc::Inquirer::TheRequestsMap;
+ unsigned int Ipc::Inquirer::LastRequestId = 0;
+ /// compare Ipc::StrandCoord using kidId, for std::sort() below
+ static bool
+ LesserStrandByKidId(const Ipc::StrandCoord &c1, const Ipc::StrandCoord &c2)
+ {
+     return c1.kidId < c2.kidId;
+ }
+ Ipc::Inquirer::Inquirer(Request::Pointer aRequest, const StrandCoords& coords,
+                         double aTimeout):
+         AsyncJob("Ipc::Inquirer"),
+         request(aRequest), strands(coords), pos(strands.begin()), timeout(aTimeout)
+ {
+     debugs(54, 5, HERE);
+     // order by ascending kid IDs; useful for non-aggregatable stats
+     std::sort(strands.begin(), strands.end(), LesserStrandByKidId);
+ }
+ Ipc::Inquirer::~Inquirer()
+ {
+     debugs(54, 5, HERE);
+     cleanup();
+ }
+ void
+ Ipc::Inquirer::cleanup()
+ {
+ }
+ void
+ Ipc::Inquirer::start()
+ {
+     request->requestId = 0;
+ }
+ void
+ Ipc::Inquirer::inquire()
+ {
+     if (pos == strands.end()) {
+         Must(done());
+         return;
+     }
+     Must(request->requestId == 0);
+     AsyncCall::Pointer callback = asyncCall(54, 5, "Mgr::Inquirer::handleRemoteAck",
+                                             HandleAckDialer(this, &Inquirer::handleRemoteAck, NULL));
+     if (++LastRequestId == 0) // don't use zero value as request->requestId
+         ++LastRequestId;
+     request->requestId = LastRequestId;
+     const int kidId = pos->kidId;
+     debugs(54, 4, HERE << "inquire kid: " << kidId << status());
+     TheRequestsMap[request->requestId] = callback;
+     TypedMsgHdr message;
+     request->pack(message);
+     SendMessage(Port::MakeAddr(strandAddrPfx, kidId), message);
+     eventAdd("Ipc::Inquirer::requestTimedOut", &Inquirer::RequestTimedOut,
+              this, timeout, 0, false);
+ }
+ /// called when a strand is done writing its output
+ void
+ Ipc::Inquirer::handleRemoteAck(Response::Pointer response)
+ {
+     debugs(54, 4, HERE << status());
+     request->requestId = 0;
+     removeTimeoutEvent();
+     if (aggregate(response)) {
+         Must(!done()); // or we should not be called
+         ++pos; // advance after a successful inquiry
+         inquire();
+     } else {
+         mustStop("error");
+     }
+ }
+ void
+ Ipc::Inquirer::swanSong()
+ {
+     debugs(54, 5, HERE);
+     removeTimeoutEvent();
+     if (request->requestId > 0) {
+         DequeueRequest(request->requestId);
+         request->requestId = 0;
+     }
+     sendResponse();
+     cleanup();
+ }
+ bool
+ Ipc::Inquirer::doneAll() const
+ {
+     return pos == strands.end();
+ }
+ void
+ Ipc::Inquirer::handleException(const std::exception& e)
+ {
+     debugs(54, 3, HERE << e.what());
+     mustStop("exception");
+ }
+ void
+ Ipc::Inquirer::callException(const std::exception& e)
+ {
+     debugs(54, 3, HERE);
+     try {
+         handleException(e);
+     } catch (const std::exception& ex) {
+         debugs(54, DBG_CRITICAL, HERE << ex.what());
+     }
+     AsyncJob::callException(e);
+ }
+ /// returns and forgets the right Inquirer callback for strand request
+ AsyncCall::Pointer
+ Ipc::Inquirer::DequeueRequest(unsigned int requestId)
+ {
+     debugs(54, 3, HERE << " requestId " << requestId);
+     Must(requestId != 0);
+     AsyncCall::Pointer call;
+     RequestsMap::iterator request = TheRequestsMap.find(requestId);
+     if (request != TheRequestsMap.end()) {
+         call = request->second;
+         Must(call != NULL);
+         TheRequestsMap.erase(request);
+     }
+     return call;
+ }
+ void
+ Ipc::Inquirer::HandleRemoteAck(const Response& response)
+ {
+     Must(response.requestId != 0);
+     AsyncCall::Pointer call = DequeueRequest(response.requestId);
+     if (call != NULL) {
+         HandleAckDialer* dialer = dynamic_cast<HandleAckDialer*>(call->getDialer());
+         Must(dialer);
+         dialer->arg1 = response.clone();
+         ScheduleCallHere(call);
+     }
+ }
+ /// called when we are no longer waiting for the strand to respond
+ void
+ Ipc::Inquirer::removeTimeoutEvent()
+ {
+     if (eventFind(&Inquirer::RequestTimedOut, this))
+         eventDelete(&Inquirer::RequestTimedOut, this);
+ }
+ /// Ipc::Inquirer::requestTimedOut wrapper
+ void
+ Ipc::Inquirer::RequestTimedOut(void* param)
+ {
+     debugs(54, 3, HERE);
+     Must(param != NULL);
+     Inquirer* cmi = static_cast<Inquirer*>(param);
+     // use async call to enable job call protection that time events lack
+     CallJobHere(54, 5, cmi, Inquirer, requestTimedOut);
+ }
+ /// called when the strand failed to respond (or finish responding) in time
+ void
+ Ipc::Inquirer::requestTimedOut()
+ {
+     debugs(54, 3, HERE);
+     if (request->requestId != 0) {
+         DequeueRequest(request->requestId);
+         request->requestId = 0;
+         Must(!done()); // or we should not be called
+         ++pos; // advance after a failed inquiry
+         inquire();
+     }
+ }
+ const char*
+ Ipc::Inquirer::status() const
+ {
+     static MemBuf buf;
+     buf.reset();
+     buf.Printf(" [request->requestId %u]", request->requestId);
+     buf.terminate();
+     return buf.content();
+ }
diff --cc src/ipc/Port.cc
index 1b02099a6a25a65f653eb7f72a87a1f16bfeb3a7,e4a4ab33b77b38d75f9804e99f6c50e160f2e1ce..fb2fb73d8c584836f91590fee7fb532f5a47642c
@@@ -5,10 -5,9 +5,11 @@@
   *
   */
  
  #include "config.h"
 +#include "comm.h"
  #include "CommCalls.h"
 +#include "comm/Connection.h"
  #include "ipc/Port.h"
  
  const char Ipc::coordinatorAddr[] = DEFAULT_PREFIX "/var/run/coordinator.ipc";
index d39f829aae68847ed172bc715e1245760ad44883,6b76b96acf5893b24b1fc45d2bb4eca12b81686b..25451ef94b07962b91bf24e8a83abee680ab4afe
@@@ -6,9 -6,9 +6,10 @@@
   */
  
  #include "config.h"
- #include "base/TextException.h"
+ #include <map>
  #include "comm.h"
+ #include "base/TextException.h"
 +#include "comm/Connection.h"
  #include "ipc/Port.h"
  #include "ipc/Messages.h"
  #include "ipc/Kids.h"
@@@ -16,8 -16,7 +17,6 @@@
  #include "ipc/StartListening.h"
  #include "ipc/SharedListen.h"
  
- #include <map>
--
  /// holds information necessary to handle JoinListen response
  class PendingOpenRequest
  {
index 0604dc95d6077db3902505574b534a4d63bbfde9,99354133b4d2d116a5529974b7d805e8088d2772..df4f12d84090dae5eff8a5f3e40fe6a1ac26413d
@@@ -8,11 -8,9 +8,11 @@@
  #ifndef SQUID_IPC_START_LISTENING_H
  #define SQUID_IPC_START_LISTENING_H
  
- #include "base/AsyncCall.h"
 +#include "base/Subscription.h"
 +#include "comm/forward.h"
  #include "ip/forward.h"
  #include "ipc/FdNotes.h"
+ #include "base/AsyncCall.h"
  
  #if HAVE_IOSFWD
  #include <iosfwd>
Simple merge
index 58f65ee5fbcda615882bf7644b53b34370b68a62,af7edc2b7333acc74650e526b43e3a6c7e3c5c60..7230e37b34d9775cc1128634d5b27faf36749a28
@@@ -4,12 -4,13 +4,14 @@@
   * DEBUG: section 54    Interprocess Communication
   *
   */
  #include "config.h"
- #include "base/TextException.h"
  #include "comm.h"
  #include "CommCalls.h"
 +#include "comm/Connection.h"
  #include "comm/Write.h"
+ #include "base/TextException.h"
  #include "ipc/UdsOp.h"
  
  
@@@ -134,3 -132,23 +136,23 @@@ void Ipc::SendMessage(const String& toA
  {
      AsyncJob::Start(new UdsSender(toAddress, message));
  }
 -int Ipc::ImportFdIntoComm(int fd, int socktype, int protocol, Ipc::FdNoteId noteId)
 -    if (getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
 -        Ip::Address ipAddr(addr);
++const Comm::ConnectionPointer &
++Ipc::ImportFdIntoComm(const Comm::ConnectionPointer &conn, int socktype, int protocol, Ipc::FdNoteId noteId)
+ {
+     struct sockaddr_in addr;
+     socklen_t len = sizeof(addr);
 -        ipAddr.GetAddrInfo(addr_info);
++    if (getsockname(conn->fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
++        conn->remote = addr;
+         struct addrinfo* addr_info = NULL;
 -        comm_import_opened(fd, ipAddr, COMM_NONBLOCKING, Ipc::FdNote(noteId), addr_info);
 -        ipAddr.FreeAddrInfo(addr_info);
++        conn->remote.GetAddrInfo(addr_info);
+         addr_info->ai_socktype = socktype;
+         addr_info->ai_protocol = protocol;
 -        debugs(54, DBG_CRITICAL, HERE << "ERROR: FD " << fd << ' ' << xstrerror());
 -        ::close(fd);
 -        fd = -1;
++        comm_import_opened(conn, Ipc::FdNote(noteId), addr_info);
++        conn->remote.FreeAddrInfo(addr_info);
+     } else {
 -    return fd;
++        debugs(54, DBG_CRITICAL, "ERROR: Ipc::ImportFdIntoComm: " << conn << ' ' << xstrerror());
++        conn->close();
+     }
++    return conn;
+ }
diff --cc src/ipc/UdsOp.h
index 87667146c9ca29f975be473e40c000cef4b9e22c,bea34d3a6e6015f65edab9d495b8ba6ce6aabd5c..e66a7785fbdf23ac3f90fc7e48f416bd15ce816a
@@@ -11,8 -11,8 +11,9 @@@
  
  #include "SquidString.h"
  #include "base/AsyncJob.h"
 +#include "comm/forward.h"
  #include "ipc/TypedMsgHdr.h"
+ #include "ipc/FdNotes.h"
  
  class CommTimeoutCbParams;
  class CommIoCbParams;
@@@ -91,6 -91,8 +92,8 @@@ private
  
  
  void SendMessage(const String& toAddress, const TypedMsgHdr& message);
 -int ImportFdIntoComm(int fd, int socktype, int protocol, FdNoteId noteId);
+ /// import socket fd from another strand into our Comm state
++const Comm::ConnectionPointer & ImportFdIntoComm(const Comm::ConnectionPointer &conn, int socktype, int protocol, FdNoteId noteId);
  
  
  }
Simple merge
Simple merge
diff --cc src/main.cc
index f2d1aac786c67b74ec3f81568c8e4eb14d5b091c,67e110fee9b83d5967b636c39ea3d04dc35b7e25..485f1726bb64c190368342531534887c7a8a4cd0
  
  #include "squid.h"
  #include "AccessLogEntry.h"
- #include "acl/Acl.h"
- #include "acl/Asn.h"
 +#if USE_ADAPTATION
 +#include "adaptation/Config.h"
 +#endif
 +#if USE_ECAP
 +#include "adaptation/ecap/Config.h"
 +#endif
  #if ICAP_CLIENT
 +#include "adaptation/icap/Config.h"
  #include "adaptation/icap/icap_log.h"
  #endif
+ #if USE_AUTH
  #include "auth/Gadgets.h"
+ #endif
 +#include "base/Subscription.h"
  #include "base/TextException.h"
  #if USE_DELAY_POOLS
  #include "ClientDelayConfig.h"
  #include "event.h"
  #include "EventLoop.h"
  #include "ExternalACL.h"
- #include "htcp.h"
- #include "HttpReply.h"
++#include "fs/Module.h"
++#include "PeerSelectState.h"
+ #include "Store.h"
  #include "ICP.h"
  #include "ident/Ident.h"
- #include "ip/tools.h"
- #include "ipc/Coordinator.h"
+ #include "HttpReply.h"
+ #include "pconn.h"
+ #include "Mem.h"
+ #include "acl/Asn.h"
+ #include "acl/Acl.h"
+ #include "htcp.h"
+ #include "StoreFileSystem.h"
+ #include "DiskIO/DiskIOModule.h"
  #include "ipc/Kids.h"
+ #include "ipc/Coordinator.h"
  #include "ipc/Strand.h"
- #include "DiskIO/DiskIOModule.h"
- #if USE_SQUID_ESI
- #include "esi/Module.h"
- #endif
+ #include "ip/tools.h"
+ #include "SquidTime.h"
+ #include "SwapDir.h"
  #include "forward.h"
- #include "fs/Module.h"
+ #include "MemPool.h"
  #include "icmp/IcmpSquid.h"
  #include "icmp/net_db.h"
  #if USE_LOADABLE_MODULES
  #include "LoadableModules.h"
  #endif
index 5adce852647f4c7f245760cc6063dbd199e35906,5adce852647f4c7f245760cc6063dbd199e35906..5fa0e4ba7940d9ce3ac90e3033a7d28b5626c81f
@@@ -6,6 -6,6 +6,7 @@@
   */
  
  #include "config.h"
++#include "comm/Connection.h"
  #include "HttpReply.h"
  #include "ipc/Port.h"
  #include "mgr/ActionCreator.h"
@@@ -69,7 -69,7 +70,7 @@@ Mgr::Action::respond(const Request& req
      // Assume most kid classes are fully aggregatable (i.e., they do not dump
      // local info at all). Do not import the remote HTTP fd into our Comm
      // space; collect and send an IPC msg with collected info to Coordinator.
--    ::close(request.fd);
++    request.conn->close();
      collect();
      sendResponse(request.requestId);
  }
index fdec19287aeeeadef0538fefb43e517f232cb144,4ea3f8d34ea9b1f31738d9ec12c1c97c2e3c3ab7..29e4d289d53e6448aef33586ab7a273ddd238bba
@@@ -8,8 -8,7 +8,8 @@@
  #include "config.h"
  #include "base/AsyncJobCalls.h"
  #include "base/TextException.h"
- #include "comm/Connection.h"
  #include "CommCalls.h"
++#include "comm/Connection.h"
  #include "errorpage.h"
  #include "HttpReply.h"
  #include "HttpRequest.h"
  
  CBDATA_NAMESPACED_CLASS_INIT(Mgr, Forwarder);
  
- Mgr::Forwarder::RequestsMap Mgr::Forwarder::TheRequestsMap;
- unsigned int Mgr::Forwarder::LastRequestId = 0;
  
- Mgr::Forwarder::Forwarder(const Comm::ConnectionPointer &conn, const ActionParams &aParams,
 -Mgr::Forwarder::Forwarder(int aFd, const ActionParams &aParams,
++Mgr::Forwarder::Forwarder(const Comm::ConnectionPointer &aConn, const ActionParams &aParams,
                            HttpRequest* aRequest, StoreEntry* anEntry):
-         AsyncJob("Mgr::Forwarder"),
-         params(aParams),
-         request(aRequest), entry(anEntry), clientConnection(conn), requestId(0), closer(NULL)
 -        Ipc::Forwarder(new Request(KidIdentifier, 0, aFd, aParams), 10),
 -        httpRequest(aRequest), entry(anEntry), fd(aFd)
++        Ipc::Forwarder(new Request(KidIdentifier, 0, aConn, aParams), 10),
++        httpRequest(aRequest), entry(anEntry), conn(aConn)
  {
-     debugs(16, 5, HERE << clientConnection);
-     Must(Comm::IsConnOpen(clientConnection));
-     Must(request != NULL);
 -    debugs(16, 5, HERE << "FD " << fd);
 -    Must(fd >= 0);
++    debugs(16, 5, HERE << conn);
++    Must(Comm::IsConnOpen(conn));
+     Must(httpRequest != NULL);
      Must(entry != NULL);
  
-     HTTPMSGLOCK(request);
+     HTTPMSGLOCK(httpRequest);
      entry->lock();
      EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT);
  
      closer = asyncCall(16, 5, "Mgr::Forwarder::noteCommClosed",
                         CommCbMemFunT<Forwarder, CommCloseCbParams>(this, &Forwarder::noteCommClosed));
-     comm_add_close_handler(clientConnection->fd, closer);
 -    comm_add_close_handler(fd, closer);
++    comm_add_close_handler(conn->fd, closer);
  }
  
  Mgr::Forwarder::~Forwarder()
  
  /// closes our copy of the client HTTP connection socket
  void
- Mgr::Forwarder::close()
+ Mgr::Forwarder::cleanup()
  {
-     if (Comm::IsConnOpen(clientConnection)) {
 -    if (fd >= 0) {
++    if (Comm::IsConnOpen(conn)) {
          if (closer != NULL) {
-             comm_remove_close_handler(clientConnection->fd, closer);
 -            comm_remove_close_handler(fd, closer);
++            comm_remove_close_handler(conn->fd, closer);
              closer = NULL;
          }
-         clientConnection->close();
 -        comm_close(fd);
 -        fd = -1;
++        conn->close();
      }
++    conn = NULL;
  }
  
  void
@@@ -103,30 -76,27 +77,26 @@@ Mgr::Forwarder::handleError(
  }
  
  void
- Mgr::Forwarder::swanSong()
+ Mgr::Forwarder::handleTimeout()
  {
-     debugs(16, 5, HERE);
-     removeTimeoutEvent();
-     if (requestId > 0) {
-         DequeueRequest(requestId);
-         requestId = 0;
-     }
-     close();
+     sendError(errorCon(ERR_LIFETIME_EXP, HTTP_REQUEST_TIMEOUT, httpRequest));
+     Ipc::Forwarder::handleTimeout();
  }
  
- bool
- Mgr::Forwarder::doneAll() const
+ void
+ Mgr::Forwarder::handleException(const std::exception& e)
  {
-     debugs(16, 5, HERE);
-     return requestId == 0;
 -    if (entry != NULL && httpRequest != NULL && fd >= 0)
++    if (entry != NULL && httpRequest != NULL && Comm::IsConnOpen(conn))
+         sendError(errorCon(ERR_INVALID_RESP, HTTP_INTERNAL_SERVER_ERROR, httpRequest));
+     Ipc::Forwarder::handleException(e);
  }
  
  /// called when the client socket gets closed by some external force
  void
- Mgr::Forwarder::noteCommClosed(const CommCloseCbParams &io)
+ Mgr::Forwarder::noteCommClosed(const CommCloseCbParams& params)
  {
      debugs(16, 5, HERE);
-     Must(!Comm::IsConnOpen(clientConnection));
 -    Must(fd == params.fd);
 -    fd = -1;
++    conn = NULL; // needed?
      mustStop("commClosed");
  }
  
index f3cf15d87d5b67491cd6007709a53f4027ff3fef,1c8b9e84f556eda7d46f68188e86194b29b334e9..473c5432389931262c37a53f33c922dc9ce42d2b
@@@ -8,10 -8,8 +8,9 @@@
  #ifndef SQUID_MGR_FORWARDER_H
  #define SQUID_MGR_FORWARDER_H
  
- #include "base/AsyncJob.h"
 +#include "comm/forward.h"
+ #include "ipc/Forwarder.h"
  #include "mgr/ActionParams.h"
- #include <map>
  
  
  class CommCloseCbParams;
@@@ -26,50 -24,31 +25,31 @@@ namespace Mg
   * Waits for an ACK from Coordinator while holding the Store entry.
   * Fills the store entry with an error response if forwarding fails.
   */
- class Forwarder: public AsyncJob
+ class Forwarder: public Ipc::Forwarder
  {
  public:
-     Forwarder(const Comm::ConnectionPointer &conn, const ActionParams &aParams, HttpRequest* aRequest,
 -    Forwarder(int aFd, const ActionParams &aParams, HttpRequest* aRequest,
++    Forwarder(const Comm::ConnectionPointer &aConn, const ActionParams &aParams, HttpRequest* aRequest,
                StoreEntry* anEntry);
      virtual ~Forwarder();
  
-     /// finds and calls the right Forwarder upon Coordinator's response
-     static void HandleRemoteAck(unsigned int requestId);
-     /* has-to-be-public AsyncJob API */
-     virtual void callException(const std::exception& e);
  protected:
-     /* AsyncJob API */
-     virtual void start();
-     virtual void swanSong();
-     virtual bool doneAll() const;
+     /* Ipc::Forwarder API */
+     virtual void cleanup(); ///< perform cleanup actions
+     virtual void handleError();
+     virtual void handleTimeout();
+     virtual void handleException(const std::exception& e);
+     virtual void handleRemoteAck();
  
  private:
-     void handleRemoteAck();
-     static void RequestTimedOut(void* param);
-     void requestTimedOut();
-     void quitOnError(const char *reason, ErrorState *error);
      void noteCommClosed(const CommCloseCbParams& params);
-     void removeTimeoutEvent();
-     static AsyncCall::Pointer DequeueRequest(unsigned int requestId);
-     static void Abort(void* param);
-     void close();
+     void sendError(ErrorState* error);
  
  private:
-     ActionParams params; ///< action parameters to pass to the other side
-     HttpRequest* request; ///< HTTP client request for detailing errors
+     HttpRequest* httpRequest; ///< HTTP client request for detailing errors
      StoreEntry* entry; ///< Store entry expecting the response
-     Comm::ConnectionPointer clientConnection; ///< HTTP client connection descriptor
-     unsigned int requestId; ///< request id
 -    int fd; ///< HTTP client connection descriptor
++    Comm::ConnectionPointer conn; ///< HTTP client connection descriptor
      AsyncCall::Pointer closer; ///< comm_close handler for the HTTP connection
  
-     /// maps requestId to Forwarder::handleRemoteAck callback
-     typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
-     static RequestsMap TheRequestsMap; ///< pending Coordinator requests
-     static unsigned int LastRequestId; ///< last requestId used
      CBDATA_CLASS2(Forwarder);
  };
  
index 05d1129ca336d1cf829623fb0636754cf15cc86d,6fd0f97c1a4140c747f49aff832b08f886de0501..b236842a5ecc8d61151f447cde5502dee69f4072
@@@ -7,7 -7,7 +7,8 @@@
  
  #include "config.h"
  #include "base/TextException.h"
 +#include "comm/Connection.h"
+ #include "ipc/UdsOp.h"
  #include "mgr/Command.h"
  #include "mgr/Filler.h"
  #include "mgr/FunAction.h"
@@@ -32,10 -32,10 +33,10 @@@ voi
  Mgr::FunAction::respond(const Request& request)
  {
      debugs(16, 5, HERE);
-     const Comm::ConnectionPointer client = ImportHttpFdIntoComm(request.fd);
-     Must(Comm::IsConnOpen(client));
 -    const int fd = Ipc::ImportFdIntoComm(request.fd, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket);
 -    Must(fd >= 0);
++    Ipc::ImportFdIntoComm(request.conn, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket);
++    Must(Comm::IsConnOpen(request.conn));
      Must(request.requestId != 0);
-     AsyncJob::Start(new Mgr::Filler(this, client, request.requestId));
 -    AsyncJob::Start(new Mgr::Filler(this, fd, request.requestId));
++    AsyncJob::Start(new Mgr::Filler(this, request.conn, request.requestId));
  }
  
  void
index 17ec7590cca05eef630b4210e49954a23f72279d,eb5760ba0b86236bc867a0d2a74444a2e15c35ac..6e051141fc9efd1d891a349b2b3a1f457a95a7ad
@@@ -7,9 -7,9 +7,10 @@@
  
  #include "config.h"
  #include "base/TextException.h"
 +#include "comm/Connection.h"
  #include "HttpReply.h"
  #include "ipc/Messages.h"
+ #include "ipc/UdsOp.h"
  #include "ipc/TypedMsgHdr.h"
  #include "mgr/Filler.h"
  #include "mgr/InfoAction.h"
@@@ -156,10 -156,10 +157,10 @@@ voi
  Mgr::InfoAction::respond(const Request& request)
  {
      debugs(16, 5, HERE);
-     Comm::ConnectionPointer client = ImportHttpFdIntoComm(request.fd);
-     Must(Comm::IsConnOpen(client));
 -    int fd = Ipc::ImportFdIntoComm(request.fd, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket);
 -    Must(fd >= 0);
++    Ipc::ImportFdIntoComm(request.conn, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket);
++    Must(Comm::IsConnOpen(request.conn));
      Must(request.requestId != 0);
-     AsyncJob::Start(new Mgr::Filler(this, client, request.requestId));
 -    AsyncJob::Start(new Mgr::Filler(this, fd, request.requestId));
++    AsyncJob::Start(new Mgr::Filler(this, request.conn, request.requestId));
  }
  
  void
index e6e873b0d1bce74b10048933c0caf78f4c4f29c6,09c0bfd30ee114e6672b1db46af5586d2190db00..4f611dd966878d3a375332fcd1bdc466cb4fe495
@@@ -7,15 -7,15 +7,16 @@@
  
  #include "config.h"
  #include "base/TextException.h"
- #include "comm.h"
++#include "comm/Connection.h"
  #include "comm/Write.h"
  #include "CommCalls.h"
- #include "comm/Connection.h"
  #include "HttpReply.h"
- #include "ipc/Coordinator.h"
+ #include "HttpRequest.h"
+ #include "ipc/UdsOp.h"
  #include "mgr/ActionWriter.h"
- #include "mgr/Command.h"
+ #include "mgr/IntParam.h"
  #include "mgr/Inquirer.h"
+ #include "mgr/Command.h"
  #include "mgr/Request.h"
  #include "mgr/Response.h"
  #include "SquidTime.h"
  
  CBDATA_NAMESPACED_CLASS_INIT(Mgr, Inquirer);
  
- Mgr::Inquirer::RequestsMap Mgr::Inquirer::TheRequestsMap;
- unsigned int Mgr::Inquirer::LastRequestId = 0;
- /// compare Ipc::StrandCoord using kidId, for std::sort() below
- static bool
- LesserStrandByKidId(const Ipc::StrandCoord &c1, const Ipc::StrandCoord &c2)
- {
-     return c1.kidId < c2.kidId;
- }
  
- Mgr::Inquirer::Inquirer(Action::Pointer anAction, const Comm::ConnectionPointer &conn,
+ Mgr::Inquirer::Inquirer(Action::Pointer anAction,
                          const Request &aCause, const Ipc::StrandCoords &coords):
-         AsyncJob("Mgr::Inquirer"),
-         aggrAction(anAction),
-         cause(aCause),
-         clientConnection(conn),
-         strands(coords), pos(strands.begin()),
-         requestId(0), closer(NULL), timeout(aggrAction->atomic() ? 10 : 100)
+         Ipc::Inquirer(aCause.clone(), applyQueryParams(coords, aCause.params.queryParams), anAction->atomic() ? 10 : 100),
 -        aggrAction(anAction),
 -        fd(Ipc::ImportFdIntoComm(aCause.fd, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket))
++        aggrAction(anAction)
  {
-     debugs(16, 5, HERE << conn << " action: " << aggrAction);
 -    debugs(16, 5, HERE << "FD " << fd << " action: " << aggrAction);
++    conn = aCause.conn;
++    Ipc::ImportFdIntoComm(conn, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket);
 +
-     // order by ascending kid IDs; useful for non-aggregatable stats
-     std::sort(strands.begin(), strands.end(), LesserStrandByKidId);
++    debugs(16, 5, HERE << conn << " action: " << aggrAction);
  
      closer = asyncCall(16, 5, "Mgr::Inquirer::noteCommClosed",
                         CommCbMemFunT<Inquirer, CommCloseCbParams>(this, &Inquirer::noteCommClosed));
-     comm_add_close_handler(clientConnection->fd, closer);
- }
- Mgr::Inquirer::~Inquirer()
- {
-     debugs(16, 5, HERE);
-     close();
 -    comm_add_close_handler(fd, closer);
++    comm_add_close_handler(conn->fd, closer);
  }
  
  /// closes our copy of the client HTTP connection socket
  void
- Mgr::Inquirer::close()
+ Mgr::Inquirer::cleanup()
  {
-     if (Comm::IsConnOpen(clientConnection)) {
 -    if (fd >= 0) {
++    if (Comm::IsConnOpen(conn)) {
          removeCloseHandler();
-         clientConnection->close();
 -        comm_close(fd);
 -        fd = -1;
++        conn->close();
      }
  }
  
@@@ -74,7 -55,7 +57,7 @@@ voi
  Mgr::Inquirer::removeCloseHandler()
  {
      if (closer != NULL) {
-         comm_remove_close_handler(clientConnection->fd, closer);
 -        comm_remove_close_handler(fd, closer);
++        comm_remove_close_handler(conn->fd, closer);
          closer = NULL;
      }
  }
@@@ -83,16 -64,28 +66,28 @@@ voi
  Mgr::Inquirer::start()
  {
      debugs(16, 5, HERE);
-     Must(Comm::IsConnOpen(clientConnection));
+     Ipc::Inquirer::start();
 -    Must(fd >= 0);
++    Must(Comm::IsConnOpen(conn));
      Must(aggrAction != NULL);
  
-     std::auto_ptr<HttpReply> reply(new HttpReply);
-     reply->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime);
-     reply->header.putStr(HDR_CONNECTION, "close"); // until we chunk response
-     std::auto_ptr<MemBuf> replyBuf(reply->pack());
+     std::auto_ptr<MemBuf> replyBuf;
+     if (strands.empty()) {
+         LOCAL_ARRAY(char, url, MAX_URL);
+         snprintf(url, MAX_URL, "%s", aggrAction->command().params.httpUri.termedBuf());
+         HttpRequest *req = HttpRequest::CreateFromUrl(url);
+         ErrorState *err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND, req);
+         std::auto_ptr<HttpReply> reply(err->BuildHttpReply());
+         replyBuf.reset(reply->pack());
+         errorStateFree(err);
+     } else {
+         std::auto_ptr<HttpReply> reply(new HttpReply);
+         reply->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime);
+         reply->header.putStr(HDR_CONNECTION, "close"); // until we chunk response
+         replyBuf.reset(reply->pack());
+     }
      writer = asyncCall(16, 5, "Mgr::Inquirer::noteWroteHeader",
                         CommCbMemFunT<Inquirer, CommIoCbParams>(this, &Inquirer::noteWroteHeader));
-     Comm::Write(clientConnection, replyBuf.get(), writer);
 -    Comm::Write(fd, replyBuf.get(), writer);
++    Comm::Write(conn, replyBuf.get(), writer);
  }
  
  /// called when we wrote the response header
@@@ -102,77 -95,39 +97,39 @@@ Mgr::Inquirer::noteWroteHeader(const Co
      debugs(16, 5, HERE);
      writer = NULL;
      Must(params.flag == COMM_OK);
-     Must(clientConnection != NULL && params.fd == clientConnection->fd);
 -    Must(params.fd == fd);
++    Must(params.conn.getRaw() == conn.getRaw());
      Must(params.size != 0);
      // start inquiries at the initial pos
      inquire();
  }
  
+ /// called when the HTTP client or some external force closed our socket
  void
- Mgr::Inquirer::inquire()
+ Mgr::Inquirer::noteCommClosed(const CommCloseCbParams& params)
  {
-     if (pos == strands.end()) {
-         Must(done());
-         return;
-     }
-     Must(requestId == 0);
-     AsyncCall::Pointer callback = asyncCall(16, 5, "Mgr::Inquirer::handleRemoteAck",
-                                             HandleAckDialer(this, &Inquirer::handleRemoteAck, Response()));
-     if (++LastRequestId == 0) // don't use zero value as requestId
-         ++LastRequestId;
-     requestId = LastRequestId;
-     const int kidId = pos->kidId;
-     debugs(16, 4, HERE << "inquire kid: " << kidId << status());
-     TheRequestsMap[requestId] = callback;
-     Request mgrRequest(KidIdentifier, requestId, clientConnection,
-                        aggrAction->command().params);
-     Ipc::TypedMsgHdr message;
-     mgrRequest.pack(message);
-     Ipc::SendMessage(Ipc::Port::MakeAddr(Ipc::strandAddrPfx, kidId), message);
-     eventAdd("Mgr::Inquirer::requestTimedOut", &Inquirer::RequestTimedOut,
-              this, timeout, 0, false);
+     debugs(16, 5, HERE);
 -    Must(fd < 0 || fd == params.fd);
 -    fd = -1;
++    Must(!Comm::IsConnOpen(conn) && params.conn.getRaw() == conn.getRaw());
++    conn = NULL;
+     mustStop("commClosed");
  }
  
- /// called when a strand is done writing its output
- void
- Mgr::Inquirer::handleRemoteAck(const Response& response)
+ bool
+ Mgr::Inquirer::aggregate(Ipc::Response::Pointer aResponse)
  {
-     debugs(16, 4, HERE << status());
-     requestId = 0;
-     removeTimeoutEvent();
+     Mgr::Response& response = static_cast<Response&>(*aResponse);
      if (response.hasAction())
          aggrAction->add(response.getAction());
-     Must(!done()); // or we should not be called
-     ++pos; // advance after a successful inquiry
-     inquire();
- }
- /// called when the HTTP client or some external force closed our socket
- void
- Mgr::Inquirer::noteCommClosed(const CommCloseCbParams& params)
- {
-     debugs(16, 5, HERE);
-     Must(!Comm::IsConnOpen(clientConnection) || clientConnection->fd == params.fd);
-     clientConnection = NULL; // AYJ: Do we actually have to NULL it?
-     mustStop("commClosed");
+     return true;
  }
  
  void
- Mgr::Inquirer::swanSong()
+ Mgr::Inquirer::sendResponse()
  {
-     debugs(16, 5, HERE);
-     removeTimeoutEvent();
-     if (requestId > 0) {
-         DequeueRequest(requestId);
-         requestId = 0;
-     }
-     if (aggrAction->aggregatable()) {
+     if (!strands.empty() && aggrAction->aggregatable()) {
          removeCloseHandler();
-         AsyncJob::Start(new ActionWriter(aggrAction, clientConnection));
-         clientConnection = NULL; // should not close fd because we passed it to ActionWriter
 -        AsyncJob::Start(new ActionWriter(aggrAction, fd));
 -        fd = -1; // should not close fd because we passed it to ActionWriter
++        AsyncJob::Start(new ActionWriter(aggrAction, conn));
++        conn = NULL; // should not close because we passed it to ActionWriter
      }
-     close();
  }
  
  bool
index 81087133271ffedc6e79f654cd5187d50db59ade,c8e6cc8673fc57dc370ff041d24219b2b21ac099..6d9bcd6b3e5a0b7e930cdfa404ec8c51632431bf
@@@ -8,14 -8,8 +8,9 @@@
  #ifndef SQUID_MGR_INQUIRER_H
  #define SQUID_MGR_INQUIRER_H
  
- #include "base/AsyncJobCalls.h"
- #include "base/AsyncJob.h"
 +#include "comm/forward.h"
- #include "ipc/StrandCoords.h"
- #include "MemBuf.h"
+ #include "ipc/Inquirer.h"
  #include "mgr/Action.h"
- #include "mgr/Request.h"
- #include <map>
  
  class CommIoCbParams;
  class CommCloseCbParams;
@@@ -63,22 -44,10 +45,10 @@@ private
  private:
      Action::Pointer aggrAction; //< action to aggregate
  
-     Request cause; ///< cache manager request received from HTTP client
-     Comm::ConnectionPointer clientConnection; ///< HTTP client socket descriptor
-     Ipc::StrandCoords strands; ///< all strands we want to query, in order
-     Ipc::StrandCoords::const_iterator pos; ///< strand we should query now
 -    int fd; ///< HTTP client socket descriptor
++    Comm::ConnectionPointer conn; ///< HTTP client socket descriptor
  
-     unsigned int requestId; ///< ID of our outstanding request to strand
      AsyncCall::Pointer writer; ///< comm_write callback
      AsyncCall::Pointer closer; ///< comm_close handler
-     const double timeout; ///< number of seconds to wait for strand response
-     /// maps requestId to Inquirer::handleRemoteAck callback
-     typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
-     static RequestsMap TheRequestsMap; ///< pending strand requests
-     static unsigned int LastRequestId; ///< last requestId used
  
      CBDATA_CLASS2(Inquirer);
  };
index 045ea9b45a41b90572aeb61c7858593fa99c94fa,9e6f76e83477be681347735d9a1935e79d91b9ca..bf99adf36192de925bb5471810a40f711dcb6005
@@@ -7,30 -7,35 +7,40 @@@
  
  #include "config.h"
  #include "base/TextException.h"
 +#include "comm/Connection.h"
  #include "ipc/Messages.h"
+ #include "ipc/TypedMsgHdr.h"
  #include "mgr/ActionParams.h"
  #include "mgr/Request.h"
  
  
- Mgr::Request::Request(int aRequestorId, unsigned int aRequestId, const Comm::ConnectionPointer &conn,
 -Mgr::Request::Request(int aRequestorId, unsigned int aRequestId, int aFd,
++Mgr::Request::Request(int aRequestorId, unsigned int aRequestId, const Comm::ConnectionPointer &aConn,
                        const ActionParams &aParams):
-         requestorId(aRequestorId), requestId(aRequestId),
-         fd(conn->fd),
+         Ipc::Request(aRequestorId, aRequestId),
 -        fd(aFd), params(aParams)
++        conn(aConn),
 +        params(aParams)
  {
      Must(requestorId > 0);
-     Must(requestId != 0);
  }
  
- Mgr::Request::Request(const Ipc::TypedMsgHdr& msg)
+ Mgr::Request::Request(const Request& request):
+         Ipc::Request(request.requestorId, request.requestId),
 -        fd(request.fd), params(request.params)
++        conn(request.conn), params(request.params)
+ {
+ }
+ Mgr::Request::Request(const Ipc::TypedMsgHdr& msg):
+         Ipc::Request(0, 0)
  {
      msg.checkType(Ipc::mtCacheMgrRequest);
      msg.getPod(requestorId);
      msg.getPod(requestId);
      params = ActionParams(msg);
  
--    fd = msg.getFd();
++    conn = new Comm::Connection;
++    conn->fd = msg.getFd();
++    // For now we just have the FD.
++    // Address and connectio details wil be pulled/imported by the component later
  }
  
  void
@@@ -41,5 -46,11 +51,11 @@@ Mgr::Request::pack(Ipc::TypedMsgHdr& ms
      msg.putPod(requestId);
      params.pack(msg);
  
--    msg.putFd(fd);
++    msg.putFd(conn->fd);
+ }
+ Ipc::Request::Pointer
+ Mgr::Request::clone() const
+ {
+     return new Request(*this);
  }
index e85f37dcabf8b2d0a4a36240283d2b587fbb7852,50b29d7016c13688ade20886a8e809b75b57dbcf..45431d3249c99137ef2c4f554818c2c354ec0517
@@@ -16,19 -17,22 +17,22 @@@ namespace Mg
  {
  
  /// cache manager request
- class Request
+ class Request: public Ipc::Request
  {
  public:
-     Request(int aRequestorId, unsigned int aRequestId, const Comm::ConnectionPointer &conn,
 -    Request(int aRequestorId, unsigned int aRequestId, int aFd,
++    Request(int aRequestorId, unsigned int aRequestId, const Comm::ConnectionPointer &aConn,
              const ActionParams &aParams);
  
      explicit Request(const Ipc::TypedMsgHdr& msg); ///< from recvmsg()
-     void pack(Ipc::TypedMsgHdr& msg) const; ///< prepare for sendmsg()
+     /* Ipc::Request API */
+     virtual void pack(Ipc::TypedMsgHdr& msg) const;
+     virtual Pointer clone() const;
+ private:
+     Request(const Request& request);
  
  public:
-     int requestorId; ///< kidId of the requestor; used for response destination
-     unsigned int requestId; ///< unique for sender; matches request w/ response
--    int fd; ///< HTTP client connection descriptor
++    Comm::ConnectionPointer conn; ///< HTTP client connection descriptor
  
      ActionParams params; ///< action name and parameters
  };
index 12dfce29ef5b20a8ba9c6334349e413777eb89a7,52aed325d8e738043bfdf5346de658611704dbec..ce579052fcbef66dcaaf303ab45adb5737df3afe
@@@ -160,29 -161,6 +160,6 @@@ voi
  Mgr::StoreToCommWriter::Abort(void* param)
  {
      StoreToCommWriter* mgrWriter = static_cast<StoreToCommWriter*>(param);
 -    if (mgrWriter->fd >= 0)
 -        comm_close(mgrWriter->fd);
 +    if (Comm::IsConnOpen(mgrWriter->clientConnection))
 +        mgrWriter->clientConnection->close();
  }
- Comm::ConnectionPointer
- Mgr::ImportHttpFdIntoComm(int fd)
- {
-     Comm::ConnectionPointer result = new Comm::Connection();
-     struct sockaddr_in addr;
-     socklen_t len = sizeof(addr);
-     if (getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
-         result->fd = fd;
-         result->local = addr;
-         struct addrinfo* addr_info = NULL;
-         result->local.GetAddrInfo(addr_info);
-         addr_info->ai_socktype = SOCK_STREAM;
-         addr_info->ai_protocol = IPPROTO_TCP;
-         comm_import_opened(result, Ipc::FdNote(Ipc::fdnHttpSocket), addr_info);
-         result->local.FreeAddrInfo(addr_info);
-     } else {
-         debugs(16, DBG_CRITICAL, HERE << "ERROR: FD " << fd << ' ' << xstrerror());
-         ::close(fd);
-         fd = -1;
-     }
-     return result;
- }
Simple merge
index e00b73aa111df849072eabde0dcb845b7a490e95,c8f273847f269ed0a9ffd38fdd0d1b737e8c4b43..dcb30c55b218a205ae240b62e918fbf086d53166
@@@ -56,9 -53,15 +56,11 @@@ voi
  mcastJoinGroups(const ipcache_addrs *ia, const DnsLookupDetails &, void *datanotused)
  {
  #ifdef IP_MULTICAST_TTL
 -    int fd = theInIcpConnection;
 -
+     struct ip_mreq mr;
+     int i;
 -    int x;
 -    char c = 0;
  
      if (ia == NULL) {
-         debugs(7, DBG_CRITICAL, "ERROR: Attempting to join multicast group. Cannot resolve group hostname in DNS.");
+         debugs(7, 0, "comm_join_mcast_groups: Unknown host");
          return;
      }
  
              continue;
          }
  
-         struct ip_mreq mr;
          ia->in_addrs[i].GetInAddr(mr.imr_multiaddr);
          mr.imr_interface.s_addr = INADDR_ANY;
 -        x = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
 -                       (char *) &mr, sizeof(struct ip_mreq));
 -
 -        if (x < 0)
 -            debugs(7, 1, "comm_join_mcast_groups: FD " << fd << ", IP=" << ia->in_addrs[i]);
  
 -        x = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1);
 +        if (setsockopt(icpIncomingConn->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mr, sizeof(struct ip_mreq)) < 0)
 +            debugs(7, DBG_IMPORTANT, "ERROR: Join failed for " << icpIncomingConn << ", Multicast IP=" << ia->in_addrs[i]);
  
 -        if (x < 0)
 -            debugs(7, 1, "Can't disable multicast loopback: " << xstrerror());
 +        char c = 0;
 +        if (setsockopt(icpIncomingConn->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1) < 0)
 +            debugs(7, DBG_IMPORTANT, "ERROR: " << icpIncomingConn << " can't disable multicast loopback: " << xstrerror());
      }
  
  #endif
Simple merge
diff --cc src/pconn.cc
index 9d050523056859295bdc136a957a012904d09f14,99bf06a9e9a9147b6cee6ef12665afee69245735..ca23bceeecd49fa617fd6dba52246a9ab671f908
   */
  
  #include "squid.h"
- #include "comm.h"
 +#include "comm/Connection.h"
- #include "fde.h"
  #include "mgr/Registration.h"
- #include "pconn.h"
  #include "Store.h"
 -#include "comm.h"
+ #include "pconn.h"
++#include "comm.h"
+ #include "fde.h"
  
  #define PCONN_FDS_SZ  8       /* pconn set size, increase for better memcache hit rate */
  
index cc106f60d52d7f9c6895602c486f26e9746708a7,8715991aad259e96b187a4c45e4d94d5cb355dcf..a8200c304a74840beb2b78a8813cc9982b31aad6
   */
  
  #include "squid.h"
- #include "acl/FilledChecklist.h"
 +#include "DnsLookupDetails.h"
  #include "event.h"
- #include "forward.h"
+ #include "PeerSelectState.h"
+ #include "Store.h"
  #include "hier_code.h"
- #include "htcp.h"
- #include "HttpRequest.h"
- #include "icmp/net_db.h"
  #include "ICP.h"
- #include "PeerSelectState.h"
+ #include "HttpRequest.h"
+ #include "acl/FilledChecklist.h"
+ #include "htcp.h"
+ #include "forward.h"
  #include "SquidTime.h"
- #include "Store.h"
+ #include "icmp/net_db.h"
  
  static struct {
      int timeouts;
@@@ -74,9 -74,7 +74,8 @@@ static void peerGetSomeParent(ps_state 
  static void peerGetAllParents(ps_state *);
  static void peerAddFwdServer(FwdServer **, peer *, hier_code);
  static void peerSelectPinned(ps_state * ps);
 +static void peerSelectDnsResults(const ipcache_addrs *ia, const DnsLookupDetails &details, void *data);
  
  CBDATA_CLASS_INIT(ps_state);
  
  static void
@@@ -150,8 -138,6 +149,7 @@@ peerSelect(Comm::ConnectionList * paths
      psstate->request = HTTPMSGLOCK(request);
  
      psstate->entry = entry;
 +    psstate->paths = paths;
  
      psstate->callback = callback;
  
@@@ -414,17 -344,15 +412,17 @@@ peerSelectFoo(ps_state * ps
          break;
      }
  
 -    peerSelectCallback(ps);
 +    // resolve the possible peers
 +    peerSelectDnsPaths(ps);
  }
  
- /**
 +int peerAllowedToUse(const peer * p, HttpRequest * request);
 +
+ /*
   * peerSelectPinned
   *
-  * Selects a pinned connection.
+  * Selects a pinned connection
   */
 -int peerAllowedToUse(const peer * p, HttpRequest * request);
  static void
  peerSelectPinned(ps_state * ps)
  {
diff --cc src/protos.h
Simple merge
diff --cc src/redirect.cc
index a3cafe26c195695edde076292f42c379e3d4ab45,98e56d642288a8d5c7b4383e67aeabcb62b94149..05f0b331bffd0b0cc1d617a2308ab32873e1f276
   */
  
  #include "squid.h"
+ #if USE_AUTH
  #include "auth/UserRequest.h"
+ #endif
 +#include "comm/Connection.h"
  #include "mgr/Registration.h"
  #include "Store.h"
  #include "fde.h"
@@@ -139,15 -146,17 +147,17 @@@ redirectStart(ClientHttpRequest * http
      else
          r->client_addr.SetNoAddr();
      r->client_ident = NULL;
+ #if USE_AUTH
      if (http->request->auth_user_request != NULL)
          r->client_ident = http->request->auth_user_request->username();
-     else if (http->request->extacl_user.defined()) {
-         r->client_ident = http->request->extacl_user.termedBuf();
-     }
+     else
+ #endif
+         if (http->request->extacl_user.defined()) {
+             r->client_ident = http->request->extacl_user.termedBuf();
+         }
  
 -    if (!r->client_ident && (conn != NULL && conn->rfc931[0]))
 -        r->client_ident = conn->rfc931;
 +    if (!r->client_ident && conn != NULL && conn->clientConnection != NULL && conn->clientConnection->rfc931[0])
 +        r->client_ident = conn->clientConnection->rfc931;
  
  #if USE_SSL
  
      if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL)
          fqdn = dash_str;
  
-     snprintf(buf, 8192, "%s %s/%s %s %s myip=%s myport=%d\n",
-              r->orig_url,
-              r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
-              fqdn,
-              r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
-              r->method_s,
-              http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
-              http->request->my_addr.GetPort());
+     sz = snprintf(buf, MAX_REDIRECTOR_REQUEST_STRLEN, "%s %s/%s %s %s myip=%s myport=%d\n",
+                   r->orig_url,
+                   r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
+                   fqdn,
+                   r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
+                   r->method_s,
+                   http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
+                   http->request->my_addr.GetPort());
+     if ((sz<=0) || (sz>=MAX_REDIRECTOR_REQUEST_STRLEN)) {
+         if (sz<=0) {
+             status = HTTP_INTERNAL_SERVER_ERROR;
+             debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Can not build request to be passed to redirector. Request ABORTED.");
+         } else {
+             status = HTTP_REQUEST_URI_TOO_LARGE;
+             debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Request passed to redirector exceeds MAX_REDIRECTOR_REQUEST_STRLEN (" << MAX_REDIRECTOR_REQUEST_STRLEN << "). Request ABORTED.");
+         }
+         clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data;
+         clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+         assert (repContext);
+         Ip::Address tmpnoaddr;
+         tmpnoaddr.SetNoAddr();
+         repContext->setReplyToError(ERR_GATEWAY_FAILURE, status,
+                                     http->request->method, NULL,
 -                                    http->getConn() != NULL ? http->getConn()->peer : tmpnoaddr,
++                                    http->getConn() != NULL && http->getConn()->clientConnection != NULL ?
++                                    http->getConn()->clientConnection->remote : tmpnoaddr,
+                                     http->request,
+                                     NULL,
+ #if USE_AUTH
+                                     http->getConn() != NULL && http->getConn()->auth_user_request != NULL ?
+                                     http->getConn()->auth_user_request : http->request->auth_user_request);
+ #else
+                                     NULL);
+ #endif
+         node = (clientStreamNode *)http->client_stream.tail->data;
+         clientStreamRead(node, http, node->readBuffer);
+         return;
+     }
  
      helperSubmit(redirectors, buf, redirectHandleReply, r);
  }
index 0000000000000000000000000000000000000000,66f6f711bdbbc06965237491b80d61a1acc95e71..87b0aea5b0bd0f0685f1aaef24f8530639c74001
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,107 +1,108 @@@
+ /*
+  * $Id$
+  *
+  * DEBUG: section 49    SNMP Interface
+  *
+  */
+ #include "config.h"
+ #include "base/TextException.h"
+ #include "CommCalls.h"
++#include "comm.h"
+ #include "ipc/Port.h"
+ #include "snmp_core.h"
+ #include "snmp/Forwarder.h"
+ #include "snmp/Request.h"
+ #include "snmp/Response.h"
+ CBDATA_NAMESPACED_CLASS_INIT(Snmp, Forwarder);
+ Snmp::Forwarder::Forwarder(const Pdu& aPdu, const Session& aSession, int aFd,
+                            const Ip::Address& anAddress):
+         Ipc::Forwarder(new Request(KidIdentifier, 0, aPdu, aSession, aFd, anAddress), 2),
+         fd(aFd)
+ {
+     debugs(49, 5, HERE << "FD " << aFd);
+     Must(fd >= 0);
+     closer = asyncCall(49, 5, "Snmp::Forwarder::noteCommClosed",
+                        CommCbMemFunT<Forwarder, CommCloseCbParams>(this, &Forwarder::noteCommClosed));
+     comm_add_close_handler(fd, closer);
+ }
+ /// removes our cleanup handler of the client connection socket
+ void
+ Snmp::Forwarder::cleanup()
+ {
+     if (fd >= 0) {
+         if (closer != NULL) {
+             comm_remove_close_handler(fd, closer);
+             closer = NULL;
+         }
+         fd = -1;
+     }
+ }
+ /// called when the client socket gets closed by some external force
+ void
+ Snmp::Forwarder::noteCommClosed(const CommCloseCbParams& params)
+ {
+     debugs(49, 5, HERE);
+     Must(fd == params.fd);
+     fd = -1;
+     mustStop("commClosed");
+ }
+ void
+ Snmp::Forwarder::handleTimeout()
+ {
+     sendError(SNMP_ERR_RESOURCEUNAVAILABLE);
+     Ipc::Forwarder::handleTimeout();
+ }
+ void
+ Snmp::Forwarder::handleException(const std::exception& e)
+ {
+     debugs(49, 3, HERE << e.what());
+     if (fd >= 0)
+         sendError(SNMP_ERR_GENERR);
+     Ipc::Forwarder::handleException(e);
+ }
+ /// send error SNMP response
+ void
+ Snmp::Forwarder::sendError(int error)
+ {
+     debugs(49, 3, HERE);
+     Snmp::Request& req = static_cast<Snmp::Request&>(*request);
+     req.pdu.command = SNMP_PDU_RESPONSE;
+     req.pdu.errstat = error;
+     u_char buffer[SNMP_REQUEST_SIZE];
+     int len = sizeof(buffer);
+     snmp_build(&req.session, &req.pdu, buffer, &len);
+     comm_udp_sendto(fd, req.address, buffer, len);
+ }
+ void
+ Snmp::SendResponse(unsigned int requestId, const Pdu& pdu)
+ {
+     debugs(49, 5, HERE);
+     // snmpAgentResponse() can modify arg
+     Pdu tmp = pdu;
+     Snmp::Response response(requestId);
+     snmp_pdu* response_pdu = NULL;
+     try {
+         response_pdu = snmpAgentResponse(&tmp);
+         Must(response_pdu != NULL);
+         response.pdu = static_cast<Pdu&>(*response_pdu);
+         snmp_free_pdu(response_pdu);
+     } catch (const std::exception& e) {
+         debugs(49, DBG_CRITICAL, HERE << e.what());
+         response.pdu.command = SNMP_PDU_RESPONSE;
+         response.pdu.errstat = SNMP_ERR_GENERR;
+     }
+     Ipc::TypedMsgHdr message;
+     response.pack(message);
+     Ipc::SendMessage(Ipc::coordinatorAddr, message);
+ }
index 0000000000000000000000000000000000000000,6d748b0355f2b3ea84c37bd620b996befb848f8a..4f19e60c1b636b83a1a115c1b4aec61ae4849cc4
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,102 +1,107 @@@
 -        aggrPdu(aRequest.pdu),
 -        fd(ImportFdIntoComm(aRequest.fd, SOCK_DGRAM, IPPROTO_UDP, Ipc::fdnInSnmpSocket))
+ /*
+  * $Id$
+  *
+  * DEBUG: section 49    SNMP Interface
+  *
+  */
+ #include "config.h"
+ #include "base/TextException.h"
+ #include "CommCalls.h"
++#include "comm.h"
++#include "comm/Connection.h"
+ #include "ipc/UdsOp.h"
+ #include "snmp_core.h"
+ #include "snmp/Inquirer.h"
+ #include "snmp/Response.h"
+ #include "snmp/Request.h"
+ CBDATA_NAMESPACED_CLASS_INIT(Snmp, Inquirer);
+ Snmp::Inquirer::Inquirer(const Request& aRequest, const Ipc::StrandCoords& coords):
+         Ipc::Inquirer(aRequest.clone(), coords, 2),
 -    comm_add_close_handler(fd, closer);
++        aggrPdu(aRequest.pdu)
+ {
++    conn = new Comm::Connection;
++    conn->fd = aRequest.fd;
++    ImportFdIntoComm(conn, SOCK_DGRAM, IPPROTO_UDP, Ipc::fdnInSnmpSocket);
++
+     debugs(49, 5, HERE);
+     closer = asyncCall(49, 5, "Snmp::Inquirer::noteCommClosed",
+                        CommCbMemFunT<Inquirer, CommCloseCbParams>(this, &Inquirer::noteCommClosed));
 -    if (fd >= 0) {
++    comm_add_close_handler(conn->fd, closer);
+ }
+ /// closes our copy of the client connection socket
+ void
+ Snmp::Inquirer::cleanup()
+ {
 -            comm_remove_close_handler(fd, closer);
++    if (Comm::IsConnOpen(conn)) {
+         if (closer != NULL) {
 -        comm_close(fd);
 -        fd = -1;
++            comm_remove_close_handler(conn->fd, closer);
+             closer = NULL;
+         }
 -    Must(fd >= 0);
++        conn->close();
+     }
++    conn = NULL;
+ }
+ void
+ Snmp::Inquirer::start()
+ {
+     debugs(49, 5, HERE);
+     Ipc::Inquirer::start();
 -    Must(fd < 0 || fd == params.fd);
 -    fd = -1;
++    Must(Comm::IsConnOpen(conn));
+     inquire();
+ }
+ void
+ Snmp::Inquirer::handleException(const std::exception& e)
+ {
+     aggrPdu.errstat = SNMP_ERR_GENERR;
+     Ipc::Inquirer::handleException(e);
+ }
+ bool
+ Snmp::Inquirer::aggregate(Response::Pointer aResponse)
+ {
+     Snmp::Response& response = static_cast<Snmp::Response&>(*aResponse);
+     bool error = response.pdu.errstat != SNMP_ERR_NOERROR;
+     if (error) {
+         aggrPdu = response.pdu;
+     } else {
+         aggrPdu.aggregate(response.pdu);
+     }
+     return !error;
+ }
+ /// called when the some external force closed our socket
+ void
+ Snmp::Inquirer::noteCommClosed(const CommCloseCbParams& params)
+ {
+     debugs(49, 5, HERE);
 -    comm_udp_sendto(fd, req.address, buffer, len);
++    Must(!Comm::IsConnOpen(conn) || conn->fd == params.conn->fd);
++    conn = NULL;
+     mustStop("commClosed");
+ }
+ bool
+ Snmp::Inquirer::doneAll() const
+ {
+     return !writer && Ipc::Inquirer::doneAll();
+ }
+ void
+ Snmp::Inquirer::sendResponse()
+ {
+     debugs(49, 5, HERE);
+     aggrPdu.fixAggregate();
+     aggrPdu.command = SNMP_PDU_RESPONSE;
+     u_char buffer[SNMP_REQUEST_SIZE];
+     int len = sizeof(buffer);
+     Snmp::Request& req = static_cast<Snmp::Request&>(*request);
+     snmp_build(&req.session, &aggrPdu, buffer, &len);
++    comm_udp_sendto(conn->fd, req.address, buffer, len);
+ }
index 0000000000000000000000000000000000000000,5efcdcfee769b6654982bdd454f2c79c353b88f1..e9990a34b3c2a773a50010d36979a4672b1766b3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,54 +1,55 @@@
 -    int fd; ///< client connection descriptor
+ /*
+  * $Id$
+  *
+  * DEBUG: section 49    SNMP Interface
+  *
+  */
+ #ifndef SQUID_SNMPX_INQUIRER_H
+ #define SQUID_SNMPX_INQUIRER_H
++#include "comm/forward.h"
+ #include "ipc/Inquirer.h"
+ #include "snmp/forward.h"
+ #include "snmp/Pdu.h"
+ class CommCloseCbParams;
+ namespace Snmp
+ {
+ /// Coordinator's job that sends a PDU request to each strand,
+ /// aggregates strand responses and send back the result to client
+ class Inquirer: public Ipc::Inquirer
+ {
+ public:
+     Inquirer(const Request& aRequest, const Ipc::StrandCoords& coords);
+ protected:
+     /* AsyncJob API */
+     virtual void start();
+     virtual bool doneAll() const;
+     /* Ipc::Inquirer API */
+     virtual void cleanup();
+     virtual void handleException(const std::exception& e);
+     virtual void sendResponse();
+     virtual bool aggregate(Ipc::Response::Pointer aResponse);
+ private:
+     void noteCommClosed(const CommCloseCbParams& params);
+ private:
+     Pdu aggrPdu; ///< aggregated pdu
++    Comm::ConnectionPointer conn; ///< client connection descriptor
+     AsyncCall::Pointer writer; ///< comm_write callback
+     AsyncCall::Pointer closer; ///< comm_close handler
+     CBDATA_CLASS2(Inquirer);
+ };
+ } // namespace Snmp
+ #endif /* SQUID_SNMPX_INQUIRER_H */
index 28e7f25ed0b8310836a2193828fd67231e917d5f,fb300d2ed23deca2dea069529cb6123506dbac55..6c92a749d6532cbaf33201e6f0ad1a2e77f4ae9a
@@@ -31,9 -31,8 +31,9 @@@
   */
  #include "squid.h"
  #include "acl/FilledChecklist.h"
- #include "cache_snmp.h"
+ #include "base/CbcPointer.h"
  #include "comm.h"
 +#include "comm/Connection.h"
  #include "comm/Loops.h"
  #include "ipc/StartListening.h"
  #include "ip/Address.h"
@@@ -52,38 -50,25 +51,26 @@@ public
      SnmpListeningStartedDialer(Handler aHandler): handler(aHandler) {}
  
      virtual void print(std::ostream &os) const { startPrint(os) << ')'; }
      virtual bool canDial(AsyncCall &) const { return true; }
 -    virtual void dial(AsyncCall &) { (handler)(fd, errNo); }
 +    virtual void dial(AsyncCall &) { (handler)(conn, errNo); }
  
  public:
      Handler handler;
  };
- static void snmpPortOpened(const Comm::ConnectionPointer &conn, int errNo);
  
  
- typedef struct _mib_tree_entry mib_tree_entry;
- typedef oid *(instance_Fn) (oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
- struct _mib_tree_entry {
-     oid *name;
-     int len;
-     oid_ParseFn *parsefunction;
-     instance_Fn *instancefunction;
-     int children;
-     struct _mib_tree_entry **leaves;
 -Ip::Address theOutSNMPAddr;
++static void snmpPortOpened(const Comm::ConnectionPointer &conn, int errNo);
 +
-     struct _mib_tree_entry *parent;
- };
  
  mib_tree_entry *mib_tree_head;
  mib_tree_entry *mib_tree_last;
  
 -static void snmpIncomingConnectionOpened(int fd, int errNo);
 -static void snmpOutgoingConnectionOpened(int fd, int errNo);
 +Comm::ConnectionPointer snmpIncomingConn;
 +Comm::ConnectionPointer snmpOutgoingConn;
  
- static mib_tree_entry * snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction);
- static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...);
+ static mib_tree_entry * snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType = atNone);
+ static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType, int children,...);
  static oid *snmpCreateOid(int length,...);
  mib_tree_entry * snmpLookupNodeStr(mib_tree_entry *entry, const char *str);
  int snmpCreateOidFromStr(const char *str, oid **name, int *nl);
diff --cc src/snmp_core.h
index ca5587aa964c647be72dfb271bbd854dd38c0047,284902e5eb82354dd645f1fdbe31c258b953176a..2ce506f5730e6bf9b042c990519253102d6838aa
@@@ -1,15 -1,38 +1,41 @@@
- #ifndef _SQUID_SNMP_CORE_H
- #define _SQUID_SNMP_CORE_H
+ /*
+  * $Id$
+  *
+  * DEBUG: section 49    SNMP Interface
+  *
+  */
  
- #include "config.h"
+ #ifndef SQUID_SNMP_CORE_H
+ #define SQUID_SNMP_CORE_H
  
- #if SQUID_SNMP
+ #include "config.h"
+ #include "cache_snmp.h"
 +#include "comm/forward.h"
  
- extern Comm::ConnectionPointer snmpOutgoingConn;
- // PRIVATE? extern int theInSnmpConnection;
- // DEAD? extern char *snmp_agentinfo;
+ #define SNMP_REQUEST_SIZE 4096
+ #define MAX_PROTOSTAT 5
+ typedef struct _mib_tree_entry mib_tree_entry;
+ typedef oid *(instance_Fn) (oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
+ typedef enum {atNone = 0, atSum, atAverage, atMax, atMin} AggrType;
  
- #endif /* SQUID_SNMP */
+ struct _mib_tree_entry {
+     oid *name;
+     int len;
+     oid_ParseFn *parsefunction;
+     instance_Fn *instancefunction;
+     int children;
+     struct _mib_tree_entry **leaves;
+     struct _mib_tree_entry *parent;
+     AggrType aggrType;
+ };
+ extern struct snmp_pdu* snmpAgentResponse(struct snmp_pdu* PDU);
+ extern AggrType snmpAggrType(oid* Current, snint CurrentLen);
++extern Comm::ConnectionPointer snmpOutgoingConn;
 +
- #endif /* _SQUID_SNMP_CORE_H */
+ #endif /* SQUID_SNMP_CORE_H */
index 6eb6756a662206a6c36af504fe79512c457d7a5d,6eb6756a662206a6c36af504fe79512c457d7a5d..48f80c7fcac0e9651f80d54b74476df17dd73975
@@@ -6,6 -6,6 +6,8 @@@ noinst_LTLIBRARIES = libsslsquid.la lib
  EXTRA_PROGRAMS = \
        ssl_crtd
  
++EXTRA_DIST = stub_libsslsquid.cc stub_libsslutil.cc
++
  if USE_SSL_CRTD
  SSL_CRTD = ssl_crtd
  SSL_CRTD_SOURCE = \
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8c15b889051dbb256b78c7b0b39915d60b080761
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,60 @@@
++#include "config.h"
++#include "fatal.h"
++
++/* Stub File for the ssl/libsslsquid.la convenience library */
++
++#define STUB_BASE "ssl/libsslsquid.la"
++
++#define STUB { fatal(STUB_BASE " required."); }
++#define STUB_RETVAL(x) { fatal(STUB_BASE " required."); return (x); }
++#define STUB_RETREF(x) { fatal(STUB_BASE " required."); static x v; return v; }
++#define STUB_RETREF2(x,y) { fatal(STUB_BASE " required."); static x v((y)); return v; }
++
++#include "ssl/Config.h"
++Ssl::Config::Config() STUB
++Ssl::Config::~Config() STUB
++Ssl::Config Ssl::TheConfig;
++
++#include "ssl/context_storage.h"
++//Ssl::CertificateStorageAction::CertificateStorageAction(const Mgr::Command::Pointer &cmd) STUB
++Ssl::CertificateStorageAction::Pointer Ssl::CertificateStorageAction::Create(const Mgr::Command::Pointer &cmd) STUB_RETREF(Ssl::CertificateStorageAction::Pointer)
++void Ssl::CertificateStorageAction::dump(StoreEntry *sentry) STUB
++Ssl::LocalContextStorage::Item::Item(SSL_CTX * aSsl_ctx, std::string const & aName) STUB
++Ssl::LocalContextStorage::Item::~Item() STUB
++Ssl::LocalContextStorage::LocalContextStorage(size_t aMax_memory) STUB
++Ssl::LocalContextStorage::~LocalContextStorage() STUB
++void Ssl::LocalContextStorage::SetSize(size_t aMax_memory) STUB
++SSL_CTX * Ssl::LocalContextStorage::add(char const * host_name, SSL_CTX * ssl_ctx) STUB_RETVAL(NULL)
++SSL_CTX * Ssl::LocalContextStorage::find(char const * host_name) STUB_RETVAL(NULL)
++void Ssl::LocalContextStorage::remove(char const * host_name) STUB
++Ssl::GlobalContextStorage::GlobalContextStorage() STUB
++Ssl::GlobalContextStorage::~GlobalContextStorage() STUB
++void Ssl::GlobalContextStorage::addLocalStorage(Ip::Address const & address, size_t size_of_store) STUB
++Ssl::LocalContextStorage & Ssl::GlobalContextStorage::getLocalStorage(Ip::Address const & address) STUB_RETREF2(Ssl::LocalContextStorage, 0)
++void Ssl::GlobalContextStorage::reconfigureStart() STUB
++//Ssl::GlobalContextStorage Ssl::TheGlobalContextStorage;
++
++#include "ssl/ErrorDetail.h"
++Ssl::ssl_error_t parseErrorString(const char *name) STUB_RETVAL(0)
++const char *Ssl::getErrorName(ssl_error_t value) STUB_RETVAL(NULL)
++Ssl::ErrorDetail::ErrorDetail(ssl_error_t err_no, X509 *cert) STUB
++Ssl::ErrorDetail::ErrorDetail(ErrorDetail const &) STUB
++const String & Ssl::ErrorDetail::toString() const STUB_RETREF(String)
++
++#include "ssl/support.h"
++SSL_CTX *sslCreateServerContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *clientCA, const char *CAfile, const char *CApath, const char *CRLfile, const char *dhpath, const char *context) STUB_RETVAL(NULL)
++SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile) STUB_RETVAL(NULL)
++int ssl_read_method(int, char *, int) STUB_RETVAL(0)
++int ssl_write_method(int, const char *, int) STUB_RETVAL(0)
++void ssl_shutdown_method(int) STUB
++const char *sslGetUserEmail(SSL *ssl) STUB_RETVAL(NULL)
++// typedef char const *SSLGETATTRIBUTE(SSL *, const char *);
++// SSLGETATTRIBUTE sslGetUserAttribute;
++// SSLGETATTRIBUTE sslGetCAAttribute;
++const char *sslGetUserCertificatePEM(SSL *ssl) STUB_RETVAL(NULL)
++const char *sslGetUserCertificateChainPEM(SSL *ssl) STUB_RETVAL(NULL)
++SSL_CTX *Ssl::generateSslContext(char const *host, Ssl::X509_Pointer const & signedX509, Ssl::EVP_PKEY_Pointer const & signedPkey) STUB_RETVAL(NULL)
++bool Ssl::verifySslCertificateDate(SSL_CTX * sslContext) STUB_RETVAL(false)
++SSL_CTX * Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data) STUB_RETVAL(NULL)
++int Ssl::matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data,  ASN1_STRING *cn_data)) STUB_RETVAL(0)
++int Ssl::asn1timeToString(ASN1_TIME *tm, char *buf, int len) STUB_RETVAL(0)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5ecf4af91c9f8bdf326b79bd1bebdd70e5e4951c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,39 @@@
++#include "config.h"
++#include "fatal.h"
++
++/* Stub File for the ssl/libsslutil.la convenience library */
++
++#define STUB_BASE "ssl/libsslutil.la"
++
++#define STUB { fatal(STUB_BASE " required."); }
++#define STUB_RETVAL(x) { fatal(STUB_BASE " required."); return (x); }
++#define STUB_RETREF(x) { fatal(STUB_BASE " required."); static x v; return v; }
++#define STUB_RETREF2(x,y) { fatal(STUB_BASE " required."); static x v((y)); return v; }
++
++#include "ssl/crtd_message.h"
++Ssl::CrtdMessage::CrtdMessage() STUB
++Ssl::CrtdMessage::ParseResult Ssl::CrtdMessage::parse(const char * buffer, size_t len) STUB_RETVAL(ERROR)
++std::string const & Ssl::CrtdMessage::getBody() const STUB_RETREF(std::string)
++std::string const & Ssl::CrtdMessage::getCode() const STUB_RETREF(std::string)
++void Ssl::CrtdMessage::setBody(std::string const & aBody) STUB
++void Ssl::CrtdMessage::setCode(std::string const & aCode) STUB
++std::string Ssl::CrtdMessage::compose() const STUB_RETREF(std::string)
++void Ssl::CrtdMessage::clear() STUB
++void Ssl::CrtdMessage::parseBody(BodyParams & map, std::string & other_part) const STUB
++void Ssl::CrtdMessage::composeBody(BodyParams const & map, std::string const & other_part) STUB
++
++#include "ssl/gadgets.h"
++X509_REQ * Ssl::createNewX509Request(EVP_PKEY_Pointer const & pkey, const char * hostname) STUB_RETVAL(NULL)
++bool Ssl::writeCertAndPrivateKeyToMemory(X509_Pointer const & cert, EVP_PKEY_Pointer const & pkey, std::string & bufferToWrite) STUB_RETVAL(false)
++bool Ssl::writeCertAndPrivateKeyToFile(X509_Pointer const & cert, EVP_PKEY_Pointer const & pkey, char const * filename) STUB_RETVAL(false)
++bool Ssl::readCertAndPrivateKeyFromMemory(X509_Pointer & cert, EVP_PKEY_Pointer & pkey, char const * bufferToRead) STUB_RETVAL(false)
++X509 * Ssl::signRequest(X509_REQ_Pointer const & request, X509_Pointer const & x509, EVP_PKEY_Pointer const & pkey, ASN1_TIME * timeNotAfter, BIGNUM const * serial) STUB_RETVAL(NULL)
++bool Ssl::generateSslCertificateAndPrivateKey(char const *host, X509_Pointer const & signedX509, EVP_PKEY_Pointer const & signedPkey, X509_Pointer & cert, EVP_PKEY_Pointer & pkey, BIGNUM const* serial) STUB_RETVAL(false)
++void Ssl::readCertAndPrivateKeyFromFiles(X509_Pointer & cert, EVP_PKEY_Pointer & pkey, char const * certFilename, char const * keyFilename) STUB
++bool Ssl::sslDateIsInTheFuture(char const * date) STUB_RETVAL(false)
++
++#include "ssl/helper.h"
++Ssl::Helper * Ssl::Helper::GetInstance() STUB_RETVAL(NULL)
++void Ssl::Helper::Init() STUB
++void Ssl::Helper::Shutdown() STUB
++void Ssl::Helper::sslSubmit(Ssl::CrtdMessage const & message, HLPCB * callback, void *data) STUB
diff --cc src/stat.cc
index a4fe88811e088d52188a43f0068f2d9afefdac56,a1413ee2c6e2ecec234fb001bb9c4613470d9755..31eaa1e9dfe36a6bcb1e15b7cce44b21b750298c
  #include "squid.h"
  #include "event.h"
  #include "StoreClient.h"
+ #if USE_AUTH
  #include "auth/UserRequest.h"
+ #endif
 +#include "comm/Connection.h"
+ #include "mgr/Registration.h"
  #include "Store.h"
  #include "HttpRequest.h"
  #include "log/Tokens.h"
@@@ -2051,15 -2055,17 +2053,17 @@@ statClientRequests(StoreEntry * s
                            (long int) http->start_time.tv_sec,
                            (int) http->start_time.tv_usec,
                            tvSubDsec(http->start_time, current_time));
+ #if USE_AUTH
          if (http->request->auth_user_request != NULL)
              p = http->request->auth_user_request->username();
-         else if (http->request->extacl_user.defined()) {
-             p = http->request->extacl_user.termedBuf();
-         }
+         else
+ #endif
+             if (http->request->extacl_user.defined()) {
+                 p = http->request->extacl_user.termedBuf();
+             }
  
 -        if (!p && (conn != NULL && conn->rfc931[0]))
 -            p = conn->rfc931;
 +        if (!p && conn != NULL && conn->clientConnection->rfc931[0])
 +            p = conn->clientConnection->rfc931;
  
  #if USE_SSL
  
diff --cc src/store.cc
index f0e182bdd6b4bea6ed0d0e3e5db0cc54e94033f9,a9d24db0d94af3737467eea76a63fe3970a404d3..d574fecb9174d198e99103785005321a21fd7cb4
   */
  
  #include "squid.h"
 +#include "CacheManager.h"
 +#include "comm/Connection.h"
  #include "event.h"
- #if USE_DELAY_POOLS
- #include "DelayPools.h"
- #endif
  #include "fde.h"
+ #include "Store.h"
+ #include "mgr/Registration.h"
+ #include "StoreClient.h"
+ #include "stmem.h"
  #include "HttpReply.h"
  #include "HttpRequest.h"
- #include "mem_node.h"
  #include "MemObject.h"
- #include "mgr/Registration.h"
- #include "SquidTime.h"
- #include "Stack.h"
- #include "stmem.h"
- #include "Store.h"
- #include "StoreClient.h"
- #include "mgr/StoreIoAction.h"
+ #include "mem_node.h"
  #include "StoreMeta.h"
- #include "swap_log_op.h"
  #include "SwapDir.h"
+ #if USE_DELAY_POOLS
+ #include "DelayPools.h"
+ #endif
+ #include "Stack.h"
+ #include "SquidTime.h"
+ #include "swap_log_op.h"
+ #include "mgr/StoreIoAction.h"
  
  static STMCB storeWriteComplete;
  
@@@ -248,12 -246,15 +248,14 @@@ StoreEntry::delayAwareRead(const Comm::
          }
  
          /* delay id limit */
 -        mem_obj->mostBytesAllowed().delayRead(DeferredRead(DeferReader, this, CommRead(fd, buf, len, callback)));
 -
 +        mem_obj->mostBytesAllowed().delayRead(DeferredRead(DeferReader, this, CommRead(conn, buf, len, callback)));
          return;
  #endif
      }
  
 -    comm_read(fd, buf, amountToRead, callback);
 +    comm_read(conn, buf, amountToRead, callback);
  }
  
  size_t
diff --cc src/structs.h
Simple merge
Simple merge
index 7c749420328efce739eb655477a05dea66d39c4f,0000000000000000000000000000000000000000..c2359e84f23524d85d242c29a1a1b75b3aa7f4c5
mode 100644,000000..100644
--- /dev/null
@@@ -1,68 -1,0 +1,68 @@@
- clientdbUpdate(const Ip::Address &, log_type, protocol_t, size_t)
 +#include "config.h"
 +/* because the clientdb API is defined in protos.h still */
 +#include "protos.h"
 +
 +void
 +clientdbInit(void)
 +{
 +    fatal("client_db.cc required");
 +}
 +
 +void
++clientdbUpdate(const Ip::Address &, log_type, AnyP::ProtocolType, size_t)
 +{
 +    fatal("client_db.cc required");
 +}
 +
 +int
 +clientdbCutoffDenied(const Ip::Address &)
 +{
 +    fatal("client_db.cc required");
 +    return -1;
 +}
 +
 +void
 +clientdbDump(StoreEntry *)
 +{
 +    fatal("client_db.cc required");
 +}
 +
 +void
 +clientdbFreeMemory(void)
 +{
 +    fatal("client_db.cc required");
 +}
 +
 +int
 +clientdbEstablished(const Ip::Address &, int)
 +{
 +    fatal("client_db.cc required");
 +    return -1;
 +}
 +
 +#if USE_DELAY_POOLS
 +void
 +clientdbSetWriteLimiter(ClientInfo * info, const int writeSpeedLimit,const double initialBurst,const double highWatermark)
 +{
 +    fatal("client_db.cc required");
 +}
 +
 +ClientInfo *
 +clientdbGetInfo(const Ip::Address &addr)
 +{
 +    fatal("client_db.cc required");
 +    return NULL;
 +}
 +#endif
 +
 +void
 +clientOpenListenSockets(void)
 +{
 +    fatal("client_db.cc required");
 +}
 +
 +void
 +clientHttpConnectionsClose(void)
 +{
 +    fatal("client_db.cc required");
 +}
index 60b3ef96834de856cf1f6f414cea3b23345e1004,a2007ae53819be29d9202261a4dc6be6b259edfe..07031e57a135c36e64c5fbba193aa3ba314731a8
@@@ -91,6 -90,6 +91,7 @@@ commSetCloseOnExec(int fd
      /* for tests... ignore */
  }
  
++#if 0
  void
  Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
  {
@@@ -102,6 -101,6 +103,7 @@@ Comm::QuickPollRequired(
  {
      /* for tests ... ignore */
  }
++#endif
  
  int
  ignoreErrno(int ierrno)
@@@ -131,15 -130,15 +133,6 @@@ commUnsetNonBlocking(int fd
      return -1;
  }
  
--/* bah, cheating on stub count */
--
--pid_t
--ipcCreate(int type, const char *prog, const char *const args[], const char *name, Ip::Address &local_addr, int *rfd, int *wfd, void **hIpc)
--{
--    fatal ("Not implemented");
--    return -1;
--}
--
  void
  comm_init(void)
  {
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3fa18773c97108da1b8f44c3f3b480442ab643bb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,37 @@@
++#include "config.h"
++#include "comm/Connection.h"
++#include "ICP.h"
++#include "icp_opcode.h"
++
++#define STUB { fatal("icp_*.cc required."); }
++#define STUB_RETVAL(x) { fatal("icp_*.cc required."); return (x); }
++//#define STUB_RETREF(x) { fatal("icp_*.cc required."); static x v; return v; }
++
++#ifdef __cplusplus
++_icp_common_t::_icp_common_t() STUB
++_icp_common_t::_icp_common_t(char *buf, unsigned int len) STUB
++void _icp_common_t::handleReply(char *buf, Ip::Address &from) STUB
++_icp_common_t *_icp_common_t::createMessage(icp_opcode opcode, int flags, const char *url, int reqnum, int pad) STUB_RETVAL(NULL)
++icp_opcode _icp_common_t::getOpCode() const STUB_RETVAL(ICP_INVALID)
++ICPState::ICPState(icp_common_t &aHeader, HttpRequest *aRequest) STUB
++ICPState::~ICPState() STUB
++#endif
++
++Comm::ConnectionPointer icpIncomingConn;
++Comm::ConnectionPointer icpOutgoingConn;
++Ip::Address theIcpPublicHostID;
++
++HttpRequest* icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from) STUB_RETVAL(NULL)
++int icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request) STUB_RETVAL(0)
++void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from) STUB
++icp_opcode icpGetCommonOpcode() STUB_RETVAL(ICP_INVALID)
++int icpUdpSend(int, const Ip::Address &, icp_common_t *, log_type, int) STUB_RETVAL(0)
++log_type icpLogFromICPCode(icp_opcode opcode) STUB_RETVAL(LOG_TAG_NONE)
++void icpDenyAccess(Ip::Address &from, char *url, int reqnum, int fd) STUB
++void icpHandleIcpV3(int, Ip::Address &, char *, int) STUB
++int icpCheckUdpHit(StoreEntry *, HttpRequest * request) STUB_RETVAL(0)
++void icpConnectionsOpen(void) STUB
++void icpConnectionShutdown(void) STUB
++void icpConnectionClose(void) STUB
++int icpSetCacheKey(const cache_key * key) STUB_RETVAL(0)
++const cache_key *icpGetCacheKey(const char *url, int reqnum) STUB_RETVAL(NULL)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..57b93b7a9f47644cc3a145df9d5a6548f25fb05d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++#include "config.h"
++// because ipcCreate is defined in protos.h still
++#include "protos.h"
++
++pid_t
++ipcCreate(int type, const char *prog, const char *const args[], const char *name, Ip::Address &local_addr, int *rfd, int *wfd, void **hIpc)
++{
++    fatal("ipc.cc required.");
++    return -1;
++}
index 9832a53f9f2114c78ebc41ac1f36b70bb40361b7,5914ed05922d8d1e8680d89a8ca026cfbd285f3c..3ec3774e0a7701f42d56dd6f293e32fa8dfcf8dd
- /*
-  * $Id$
-  *
-  * DEBUG: section 20    Storage Manager
-  * AUTHOR: Robert Collins
-  *
-  * SQUID Web Proxy Cache          http://www.squid-cache.org/
-  * ----------------------------------------------------------
-  *
-  *  Squid is the result of efforts by numerous individuals from
-  *  the Internet community; see the CONTRIBUTORS file for full
-  *  details.   Many organizations have provided support for Squid's
-  *  development; see the SPONSORS file for full details.  Squid is
-  *  Copyrighted (C) 2001 by the Regents of the University of
-  *  California; see the COPYRIGHT file for full details.  Squid
-  *  incorporates software developed and/or copyrighted by other
-  *  sources; see the CREDITS file for full details.
-  *
-  *  This program is free software; you can redistribute it and/or modify
-  *  it under the terms of the GNU General Public License as published by
-  *  the Free Software Foundation; either version 2 of the License, or
-  *  (at your option) any later version.
-  *
-  *  This program is distributed in the hope that it will be useful,
-  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  *  GNU General Public License for more details.
-  *
-  *  You should have received a copy of the GNU General Public License
-  *  along with this program; if not, write to the Free Software
-  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
-  *
-  */
  #include "squid.h"
- #include "Store.h"
  
- StorePointer Store::CurrentRoot = NULL;
+ #define STUB_API "store.cc"
+ #include "tests/STUB.h"
+ /* and code defined in the wrong .cc file */
+ #include "SwapDir.h"
+ void StoreController::maintain() STUB
+ #include "RemovalPolicy.h"
+ RemovalPolicy * createRemovalPolicy(RemovalPolicySettings * settings) STUB_RETVAL(NULL)
  
- extern "C" void
- storeAppendPrintf(StoreEntry * e, const char *fmt,...)
- {
-     fatal("storeAppendPrintf: Not implemented");
- }
  
- void
- storeAppendVPrintf(StoreEntry * e, const char *fmt, va_list vargs)
+ #include "Store.h"
+ StorePointer Store::CurrentRoot = NULL;
+ StoreIoStats store_io_stats;
+ bool StoreEntry::checkDeferRead(int fd) const STUB_RETVAL(false)
+ const char *StoreEntry::getMD5Text() const STUB_RETVAL(NULL)
+ StoreEntry::StoreEntry() STUB
+ StoreEntry::StoreEntry(const char *url, const char *log_url) STUB
+ HttpReply const *StoreEntry::getReply() const STUB_RETVAL(NULL)
+ void StoreEntry::write(StoreIOBuffer) STUB
+ bool StoreEntry::isAccepting() const STUB_RETVAL(false)
+ size_t StoreEntry::bytesWanted(Range<size_t> const) const STUB_RETVAL(0)
+ void StoreEntry::complete() STUB
+ store_client_t StoreEntry::storeClientType() const STUB_RETVAL(STORE_NON_CLIENT)
+ char const *StoreEntry::getSerialisedMetaData() STUB_RETVAL(NULL)
+ void StoreEntry::replaceHttpReply(HttpReply *) STUB
+ bool StoreEntry::swapoutPossible() STUB_RETVAL(false)
+ void StoreEntry::trimMemory() STUB
+ void StoreEntry::abort() STUB
+ void StoreEntry::unlink() STUB
+ void StoreEntry::makePublic() STUB
+ void StoreEntry::makePrivate() STUB
+ void StoreEntry::setPublicKey() STUB
+ void StoreEntry::setPrivateKey() STUB
+ void StoreEntry::expireNow() STUB
+ void StoreEntry::releaseRequest() STUB
+ void StoreEntry::negativeCache() STUB
+ void StoreEntry::cacheNegatively() STUB
+ void StoreEntry::invokeHandlers() STUB
+ void StoreEntry::purgeMem() STUB
+ void StoreEntry::swapOut() STUB
+ bool StoreEntry::swapOutAble() const STUB_RETVAL(false)
+ void StoreEntry::swapOutFileClose() STUB
+ const char *StoreEntry::url() const STUB_RETVAL(NULL)
+ int StoreEntry::checkCachable() STUB_RETVAL(0)
+ int StoreEntry::checkNegativeHit() const STUB_RETVAL(0)
+ int StoreEntry::locked() const STUB_RETVAL(0)
+ int StoreEntry::validToSend() const STUB_RETVAL(0)
+ int StoreEntry::keepInMemory() const STUB_RETVAL(0)
+ void StoreEntry::createMemObject(const char *, const char *) STUB
+ void StoreEntry::dump(int debug_lvl) const STUB
+ void StoreEntry::hashDelete() STUB
+ void StoreEntry::hashInsert(const cache_key *) STUB
+ void StoreEntry::registerAbort(STABH * cb, void *) STUB
+ void StoreEntry::reset() STUB
+ void StoreEntry::setMemStatus(mem_status_t) STUB
+ void StoreEntry::timestampsSet() STUB
+ void StoreEntry::unregisterAbort() STUB
+ void StoreEntry::destroyMemObject() STUB
+ int StoreEntry::checkTooSmall() STUB_RETVAL(0)
 -void StoreEntry::delayAwareRead(int fd, char *buf, int len, AsyncCall::Pointer callback) STUB
++void StoreEntry::delayAwareRead(const Comm::ConnectionPointer&, char *buf, int len, AsyncCall::Pointer callback) STUB
+ void StoreEntry::setNoDelay (bool const) STUB
+ bool StoreEntry::modifiedSince(HttpRequest * request) const STUB_RETVAL(false)
+ bool StoreEntry::hasIfMatchEtag(const HttpRequest &request) const STUB_RETVAL(false)
+ bool StoreEntry::hasIfNoneMatchEtag(const HttpRequest &request) const STUB_RETVAL(false)
+ RefCount<Store> StoreEntry::store() const STUB_RETVAL(StorePointer())
+ size_t StoreEntry::inUseCount() STUB_RETVAL(0)
+ void StoreEntry::getPublicByRequestMethod(StoreClient * aClient, HttpRequest * request, const HttpRequestMethod& method) STUB
+ void StoreEntry::getPublicByRequest(StoreClient * aClient, HttpRequest * request) STUB
+ void StoreEntry::getPublic(StoreClient * aClient, const char *uri, const HttpRequestMethod& method) STUB
+ void *StoreEntry::operator new(size_t byteCount)
  {
-     fatal("storeAppendVPrintf: Not implemented");
+     STUB
+     return new StoreEntry();
  }
+ void StoreEntry::operator delete(void *address) STUB
+ void StoreEntry::setReleaseFlag() STUB
+ //#if USE_SQUID_ESI
+ //ESIElement::Pointer StoreEntry::cachedESITree STUB_RETVAL(NULL)
+ //#endif
+ void StoreEntry::append(char const *, int len) STUB
+ void StoreEntry::buffer() STUB
+ void StoreEntry::flush() STUB
+ int StoreEntry::unlock() STUB_RETVAL(0)
+ int64_t StoreEntry::objectLen() const STUB_RETVAL(0)
+ int64_t StoreEntry::contentLen() const STUB_RETVAL(0)
+ void StoreEntry::lock() STUB
+ void StoreEntry::release() STUB
+ NullStoreEntry *NullStoreEntry::getInstance() STUB_RETVAL(NULL)
+ const char *NullStoreEntry::getMD5Text() const STUB_RETVAL(NULL)
+ void NullStoreEntry::operator delete(void *address) STUB
+ // private virtual. Why is this linked from outside?
+ const char *NullStoreEntry::getSerialisedMetaData() STUB_RETVAL(NULL)
+ void Store::Root(Store *) STUB
+ void Store::Root(RefCount<Store>) STUB
+ void Store::Stats(StoreEntry * output) STUB
+ void Store::Maintain(void *unused) STUB
+ void Store::create() STUB
+ void Store::diskFull() STUB
+ void Store::sync() STUB
+ void Store::unlink(StoreEntry &) STUB
+ SQUIDCEXTERN size_t storeEntryInUse() STUB_RETVAL(0)
+ SQUIDCEXTERN const char *storeEntryFlags(const StoreEntry *) STUB_RETVAL(NULL)
+ void storeEntryReplaceObject(StoreEntry *, HttpReply *) STUB
+ SQUIDCEXTERN StoreEntry *storeGetPublic(const char *uri, const HttpRequestMethod& method) STUB_RETVAL(NULL)
+ SQUIDCEXTERN StoreEntry *storeGetPublicByRequest(HttpRequest * request) STUB_RETVAL(NULL)
+ SQUIDCEXTERN StoreEntry *storeGetPublicByRequestMethod(HttpRequest * request, const HttpRequestMethod& method) STUB_RETVAL(NULL)
+ SQUIDCEXTERN StoreEntry *storeCreateEntry(const char *, const char *, request_flags, const HttpRequestMethod&) STUB_RETVAL(NULL)
+ SQUIDCEXTERN void storeInit(void) STUB
+ SQUIDCEXTERN void storeConfigure(void) STUB
+ SQUIDCEXTERN void storeFreeMemory(void) STUB
+ SQUIDCEXTERN int expiresMoreThan(time_t, time_t) STUB_RETVAL(0)
+ SQUIDCEXTERN void storeAppendPrintf(StoreEntry *, const char *,...) STUB
+ void storeAppendVPrintf(StoreEntry *, const char *, va_list ap) STUB
+ SQUIDCEXTERN int storeTooManyDiskFilesOpen(void) STUB_RETVAL(0)
+ SQUIDCEXTERN void storeHeapPositionUpdate(StoreEntry *, SwapDir *) STUB
+ SQUIDCEXTERN void storeSwapFileNumberSet(StoreEntry * e, sfileno filn) STUB
+ SQUIDCEXTERN void storeFsInit(void) STUB
+ SQUIDCEXTERN void storeFsDone(void) STUB
+ SQUIDCEXTERN void storeReplAdd(const char *, REMOVALPOLICYCREATE *) STUB
+ void destroyStoreEntry(void *) STUB
+ // in Packer.cc !? SQUIDCEXTERN void packerToStoreInit(Packer * p, StoreEntry * e) STUB
+ SQUIDCEXTERN void storeGetMemSpace(int size) STUB
  
  #if !_USE_INLINE_
  #include "Store.cci"
diff --cc src/tools.cc
index 27671f8097d7f4f6d97e6313fe1c9a8b420b36a9,e98d4e7ded1eea9797e09ded15f782d1e94b00d2..878fbd97a5959511ec37058aca168976135e31b9
   */
  
  #include "squid.h"
 -#include "compat/initgroups.h"
 -#include "compat/getaddrinfo.h"
 -#include "compat/getnameinfo.h"
 -#include "compat/tempnam.h"
 +#include "base/Subscription.h"
  #include "fde.h"
 +#include "ICP.h"
  #include "ip/Intercept.h"
  #include "ip/QosConfig.h"
- #include "ipc/Coordinator.h"
- #include "ipc/Kids.h"
  #include "MemBuf.h"
  #include "ProtoPort.h"
  #include "SquidMath.h"
@@@ -88,10 -89,10 +87,11 @@@ SQUIDCEXTERN int setresuid(uid_t, uid_t
  void
  releaseServerSockets(void)
  {
+     int i;
      /* Release the main ports as early as possible */
  
-     for (int i = 0; i < NHttpSockets; i++) {
 +    // clear both http_port and https_port lists.
+     for (i = 0; i < NHttpSockets; i++) {
          if (HttpSockets[i] >= 0)
              close(HttpSockets[i]);
      }
diff --cc src/tunnel.cc
index f5173c678c7a48acfa4de3b0644decee9ebbd940,2317ed027ceedcfc90f2286f4cd950cac3886e9b..50e5bde4d4acfc39d78c88708ca62344eef14149
   */
  
  #include "squid.h"
- #include "acl/FilledChecklist.h"
+ #include "errorpage.h"
+ #include "HttpRequest.h"
+ #include "fde.h"
 +#include "Array.h"
  #include "comm.h"
 +#include "comm/Connection.h"
 +#include "comm/ConnOpener.h"
  #include "comm/Write.h"
- #include "client_side.h"
  #include "client_side_request.h"
+ #include "acl/FilledChecklist.h"
  #if USE_DELAY_POOLS
  #include "DelayId.h"
  #endif
- #include "errorpage.h"
- #include "fde.h"
- #include "HttpRequest.h"
- #include "http.h"
+ #include "client_side.h"
  #include "MemBuf.h"
 -#include "ip/tools.h"
+ #include "http.h"
 +#include "PeerSelectState.h"
  
  class TunnelStateData
  {
@@@ -96,10 -94,10 +97,11 @@@ public
          char *buf;
          int64_t *size_ptr;            /* pointer to size in an ConnStateData for logging */
  
 +        Comm::ConnectionPointer conn;    ///< The currently connected connection.
 +
      private:
 -        int fd_;
  #if USE_DELAY_POOLS
          DelayId delayId;
  #endif
  
@@@ -266,11 -271,12 +268,11 @@@ TunnelStateData::Connection::error(int 
  
  /* Read from client side and queue it for writing to the server */
  void
 -TunnelStateData::ReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data)
 +TunnelStateData::ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data)
  {
      TunnelStateData *tunnelState = (TunnelStateData *)data;
-     assert(cbdataReferenceValid(tunnelState));
+     assert (cbdataReferenceValid (tunnelState));
  
 -    assert(fd == tunnelState->client.fd());
      tunnelState->readClient(buf, len, errcode, xerrno);
  }
  
@@@ -303,21 -309,18 +306,21 @@@ TunnelStateData::copy (size_t len, comm
       */
      cbdataInternalLock(this); /* ??? should be locked by the caller... */
  
 -    /* Bump the server connection timeout on any activity */
 -    if (!fd_closed(server.fd()))
 -        commSetTimeout(server.fd(), Config.Timeout.read, tunnelTimeout, this);
 +    /* Bump the source connection read timeout on any activity */
 +    if (Comm::IsConnOpen(from.conn)) {
 +        AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
 +                                                    CommTimeoutCbPtrFun(tunnelTimeout, this));
 +        commSetConnTimeout(from.conn, Config.Timeout.read, timeoutCall);
 +    }
  
-     if (len < 0 || errcode)
+     if (errcode)
          from.error (xerrno);
 -    else if (len == 0 || fd_closed(to.fd())) {
 -        comm_close(from.fd());
 -        /* Only close the remote end if we've finished queueing data to it */
 +    else if (len == 0 || !Comm::IsConnOpen(to.conn)) {
 +        from.conn->close();
  
 -        if (from.len == 0 && !fd_closed(to.fd()) ) {
 -            comm_close(to.fd());
 +        /* Only close the remote end if we've finished queueing data to it */
 +        if (from.len == 0 && Comm::IsConnOpen(to.conn) ) {
 +            to.conn->close();
          }
      } else if (cbdataReferenceValid(this)) {
          AsyncCall::Pointer call = commCbCall(5,5, "SomeTunnelWriteHandler",
  
  /* Writes data from the client buffer to the server side */
  void
 -TunnelStateData::WriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
 +TunnelStateData::WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
  {
      TunnelStateData *tunnelState = (TunnelStateData *)data;
-     assert(cbdataReferenceValid(tunnelState));
+     assert (cbdataReferenceValid (tunnelState));
  
 -    assert(fd == tunnelState->server.fd());
      tunnelState->writeServerDone(buf, len, flag, xerrno);
  }
  
  void
  TunnelStateData::writeServerDone(char *buf, size_t len, comm_err_t flag, int xerrno)
  {
 -    debugs(26, 3, "tunnelWriteServer: FD " << server.fd() << ", " << len << " bytes written");
 +    debugs(26, 3, HERE  << server.conn << ", " << len << " bytes written");
  
-     if (flag == COMM_ERR_CLOSING)
-         return;
      /* Error? */
-     if (len < 0 || flag != COMM_OK) {
-         server.error(xerrno); // may call comm_close
+     if (flag != COMM_OK) {
+         if (flag != COMM_ERR_CLOSING)
+             server.error(xerrno); // may call comm_close
          return;
      }
  
  
  /* Writes data from the server buffer to the client side */
  void
 -TunnelStateData::WriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
 +TunnelStateData::WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
  {
      TunnelStateData *tunnelState = (TunnelStateData *)data;
-     assert(cbdataReferenceValid(tunnelState));
+     assert (cbdataReferenceValid (tunnelState));
  
 -    assert(fd == tunnelState->client.fd());
      tunnelState->writeClientDone(buf, len, flag, xerrno);
  }
  
@@@ -401,14 -404,12 +402,12 @@@ TunnelStateData::Connection::dataSent(s
  void
  TunnelStateData::writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno)
  {
 -    debugs(26, 3, "tunnelWriteClient: FD " << client.fd() << ", " << len << " bytes written");
 +    debugs(26, 3, HERE << client.conn << ", " << len << " bytes written");
  
-     if (flag == COMM_ERR_CLOSING)
-         return;
      /* Error? */
-     if (len < 0 || flag != COMM_OK) {
-         client.error(xerrno); // may call comm_close
+     if (flag != COMM_OK) {
+         if (flag != COMM_ERR_CLOSING)
+             client.error(xerrno); // may call comm_close
          return;
      }
  
@@@ -460,40 -461,85 +459,46 @@@ voi
  TunnelStateData::copyRead(Connection &from, IOCB *completion)
  {
      assert(from.len == 0);
 -    comm_read(from.fd(), from.buf, from.bytesWanted(1, SQUID_TCP_SO_RCVBUF), completion, this);
 -}
 -
 -static void
 -tunnelConnectTimeout(int fd, void *data)
 -{
 -    TunnelStateData *tunnelState = (TunnelStateData *)data;
 -    HttpRequest *request = tunnelState->request;
 -    ErrorState *err = NULL;
 -
 -    if (tunnelState->servers) {
 -        if (tunnelState->servers->_peer)
 -            hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
 -                          tunnelState->servers->_peer->host);
 -        else if (Config.onoff.log_ip_on_direct)
 -            hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
 -                          fd_table[tunnelState->server.fd()].ipaddr);
 -        else
 -            hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
 -                          tunnelState->host);
 -    } else
 -        debugs(26, 1, "tunnelConnectTimeout(): tunnelState->servers is NULL");
 -
 -    err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
 -
 -    *tunnelState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
 -
 -    err->xerrno = ETIMEDOUT;
 -
 -    err->port = tunnelState->port;
 -
 -    err->callback = tunnelErrorComplete;
 -
 -    err->callback_data = tunnelState;
 -
 -    errorSend(tunnelState->client.fd(), err);
 -    comm_close(fd);
 +    AsyncCall::Pointer call = commCbCall(5,4, "SomeTunnelReadHandler",
 +                                         CommIoCbPtrFun(completion, this));
 +    comm_read(from.conn, from.buf, from.bytesWanted(1, SQUID_TCP_SO_RCVBUF), call);
  }
  
-  * Have been written. Start the blind pump.
 +/**
 + * All the pieces we need to write to client and/or server connection
++ * have been written.
++ * - Set the HTTP status for this request.
++ * - Start the blind pump.
 + */
  static void
 -tunnelConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
 +tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
  {
      TunnelStateData *tunnelState = (TunnelStateData *)data;
  
      if (flag != COMM_OK) {
 -        tunnelErrorComplete(fd, data, 0);
++        *tunnelState->status_ptr = HTTP_INTERNAL_SERVER_ERROR;
 +        tunnelErrorComplete(conn->fd, data, 0);
          return;
      }
  
++    *tunnelState->status_ptr = HTTP_OK;
      if (cbdataReferenceValid(tunnelState)) {
          tunnelState->copyRead(tunnelState->server, TunnelStateData::ReadServer);
          tunnelState->copyRead(tunnelState->client, TunnelStateData::ReadClient);
      }
  }
  
 - * handle the write completion from a proxy request to an upstream proxy
+ /*
++ * handle the write completion from a proxy request to an upstream origin
+  */
  static void
 -tunnelProxyConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
 -{
 -    TunnelStateData *tunnelState = static_cast<TunnelStateData *>(data);
 -    debugs(26, 3, HERE << "FD " << fd << " tunnelState=" << tunnelState);
 -    if (flag == COMM_OK)
 -        *tunnelState->status_ptr = HTTP_OK;
 -    else
 -        *tunnelState->status_ptr = HTTP_INTERNAL_SERVER_ERROR;
 -    tunnelConnectedWriteDone(fd, buf, size, flag, xerrno, data);
 -}
 -
 -static void
 -tunnelConnected(int fd, void *data)
 +tunnelConnected(const Comm::ConnectionPointer &server, void *data)
  {
      TunnelStateData *tunnelState = (TunnelStateData *)data;
 -    debugs(26, 3, "tunnelConnected: FD " << fd << " tunnelState=" << tunnelState);
 -    *tunnelState->status_ptr = HTTP_OK;
 +    debugs(26, 3, HERE << server << ", tunnelState=" << tunnelState);
-     *tunnelState->status_ptr = HTTP_OK;
      AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
                                           CommIoCbPtrFun(tunnelConnectedWriteDone, tunnelState));
 -    Comm::Write(tunnelState->client.fd(), conn_established, strlen(conn_established), call, NULL);
 +    Comm::Write(tunnelState->client.conn, conn_established, strlen(conn_established), call, NULL);
  }
  
  static void
@@@ -521,67 -567,46 +526,64 @@@ tunnelConnectDone(const Comm::Connectio
      HttpRequest *request = tunnelState->request;
      ErrorState *err = NULL;
  
 -    request->recordLookup(dns);
 +#if USE_DELAY_POOLS
 +    /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
 +    if (conn->getPeer() && conn->getPeer()->options.no_delay)
 +        tunnelState->server.setDelayId(DelayId());
 +#endif
  
 -    if (tunnelState->servers->_peer)
 -        hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
 -                      tunnelState->servers->_peer->host);
 +    if (conn != NULL && conn->getPeer())
 +        hierarchyNote(&tunnelState->request->hier, conn->peerType, conn->getPeer()->host);
      else if (Config.onoff.log_ip_on_direct)
 -        hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
 -                      fd_table[tunnelState->server.fd()].ipaddr);
 +        hierarchyNote(&tunnelState->request->hier, conn->peerType, fd_table[conn->fd].ipaddr);
      else
 -        hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
 -                      tunnelState->host);
 -
 -    if (status == COMM_ERR_DNS) {
 -        debugs(26, 4, "tunnelConnect: Unknown host: " << tunnelState->host);
 -        err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND, request);
 -        *tunnelState->status_ptr = HTTP_NOT_FOUND;
 -        err->dnsError = dns.error;
 -        err->callback = tunnelErrorComplete;
 -        err->callback_data = tunnelState;
 -        errorSend(tunnelState->client.fd(), err);
 -    } else if (status != COMM_OK) {
 -        err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
 -        *tunnelState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
 -        err->xerrno = xerrno;
 -        err->port = tunnelState->port;
 -        err->callback = tunnelErrorComplete;
 -        err->callback_data = tunnelState;
 -        errorSend(tunnelState->client.fd(), err);
 -    } else {
 -        if (tunnelState->servers->_peer && !tunnelState->servers->_peer->options.originserver)
 -            tunnelProxyConnected(tunnelState->server.fd(), tunnelState);
 -        else {
 -            tunnelConnected(tunnelState->server.fd(), tunnelState);
 +        hierarchyNote(&tunnelState->request->hier, conn->peerType, tunnelState->getHost());
 +
-     // TODO: merge this into hierarchyNote with a conn parameter instead of peerType
-     request->hier.peer_local_port = conn->local.GetPort(); // for %<lp logging
 +    if (status != COMM_OK) {
 +        /* At this point only the TCP handshake has failed. no data has been passed.
 +         * we are allowed to re-try the TCP-level connection to alternate IPs for CONNECT.
 +         */
 +        tunnelState->serverDestinations.shift();
 +        if (status != COMM_TIMEOUT && tunnelState->serverDestinations.size() > 0) {
 +            /* Try another IP of this destination host */
 +            AsyncCall::Pointer call = commCbCall(26,3, "tunnelConnectDone", CommConnectCbPtrFun(tunnelConnectDone, tunnelState));
 +            Comm::ConnOpener *cs = new Comm::ConnOpener(tunnelState->serverDestinations[0], call, Config.Timeout.connect);
 +            cs->setHost(tunnelState->url);
 +            AsyncJob::Start(cs);
 +        } else {
 +            err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
 +            *tunnelState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
 +            err->xerrno = xerrno;
 +            // on timeout is this still:    err->xerrno = ETIMEDOUT;
 +            err->port = conn->remote.GetPort();
 +            err->callback = tunnelErrorComplete;
 +            err->callback_data = tunnelState;
 +            errorSend(tunnelState->client.conn, err);
          }
-         tunnelState->request->flags.proxying = 1;
 +        return;
 +    }
 +
 +    tunnelState->server.conn = conn;
 +    request->peer_host = conn->getPeer() ? conn->getPeer()->host : NULL;
 +    comm_add_close_handler(conn->fd, tunnelServerClosed, tunnelState);
 +
 +    if (conn->getPeer()) {
 +        tunnelState->request->peer_login = conn->getPeer()->login;
++        tunnelState->request->flags.proxying = (conn->getPeer()->options.originserver?0:1);
 +    } else {
 +        tunnelState->request->peer_login = NULL;
 +        tunnelState->request->flags.proxying = 0;
 +    }
  
-     if (conn->getPeer())
 -        commSetTimeout(tunnelState->server.fd(),
 -                       Config.Timeout.read,
 -                       tunnelTimeout,
 -                       tunnelState);
++    if (tunnelState->request->flags.proxying)
 +        tunnelRelayConnectRequest(conn, tunnelState);
 +    else {
 +        tunnelConnected(conn, tunnelState);
      }
 +
 +    AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
 +                                                CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
 +    commSetConnTimeout(conn, Config.Timeout.read, timeoutCall);
  }
  
  extern tos_t GetTosToServer(HttpRequest * request);
diff --cc src/typedefs.h
index 14d5809c55223bbe17a54556e416a1e3041ca26f,87e16d7c3e00af2d64b17a282813535ea8fa28cf..9ffa37cec26dc3535e9493b1596ea112e385208e
@@@ -154,8 -148,12 +148,10 @@@ class DnsLookupDetails
  typedef void FQDNH(const char *, const DnsLookupDetails &details, void *);
  typedef void IDCB(const char *ident, void *data);
  typedef void IPH(const ipcache_addrs *, const DnsLookupDetails &details, void *);
- typedef void IRCB(struct peer *, peer_t, protocol_t, void *, void *data);
+ #include "anyp/ProtocolType.h"
+ typedef void IRCB(struct peer *, peer_t, AnyP::ProtocolType, void *, void *data);
  
 -class FwdServer;
 -typedef void PSC(FwdServer *, void *);
  typedef void RH(void *data, char *);
  /* in wordlist.h */
  
diff --cc src/urn.cc
Simple merge
diff --cc src/wccp.cc
index 414d9b9a46004e62eebd447a241d40f603d1462d,fdad1a0a8229df7c5c5e374d73a071eb46bee60d..389624756eab06f48c7ce902964cf4ac78526b8c
@@@ -37,9 -37,7 +37,8 @@@
  #if USE_WCCP
  
  #include "squid.h"
  #include "comm.h"
 +#include "comm/Connection.h"
  #include "comm/Loops.h"
  #include "event.h"
  
diff --cc src/whois.cc
index f0a4326f92d5477f11646016f6e65e4bfce51e2f,f7ef8227c51cb75976077918ac99ed2f836034cb..56ed18c5e5a426679f143e5cad94f04dcaafb542
@@@ -139,67 -137,57 +139,61 @@@ WhoisState::setReplyToOK(StoreEntry *se
  }
  
  void
 -WhoisState::readReply (int fd, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno)
 +WhoisState::readReply(const Comm::ConnectionPointer &conn, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno)
  {
-     int do_next_read = 0;
      /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
-     if (flag == COMM_ERR_CLOSING) {
+     if (flag == COMM_ERR_CLOSING)
          return;
-     }
  
      aBuffer[aBufferLength] = '\0';
 -    debugs(75, 3, "whoisReadReply: FD " << fd << " read " << aBufferLength << " bytes");
 +    debugs(75, 3, HERE << conn << " read " << aBufferLength << " bytes");
      debugs(75, 5, "{" << aBuffer << "}");
  
-     if (flag == COMM_OK && aBufferLength > 0) {
-         if (!dataWritten)
-             setReplyToOK(entry);
-         kb_incr(&statCounter.server.all.kbytes_in, aBufferLength);
-         kb_incr(&statCounter.server.http.kbytes_in, aBufferLength);
-         /* No range support, we always grab it all */
-         dataWritten = true;
-         entry->append(aBuffer, aBufferLength);
-         entry->flush();
-         do_next_read = 1;
-     } else if (flag != COMM_OK || aBufferLength < 0) {
+     if (flag != COMM_OK) {
 -        debugs(50, 2, "whoisReadReply: FD " << fd << ": read failure: " << xstrerror() << ".");
 +        debugs(50, 2, HERE  << conn << ": read failure: " << xstrerror() << ".");
  
          if (ignoreErrno(errno)) {
-             do_next_read = 1;
 -            comm_read(fd, aBuffer, BUFSIZ, whoisReadReply, this);
++            AsyncCall::Pointer call = commCbCall(5,4, "whoisReadReply",
++                                                 CommIoCbPtrFun(whoisReadReply, this));
++            comm_read(conn, aBuffer, BUFSIZ, call);
          } else {
              ErrorState *err;
              err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, fwd->request);
              err->xerrno = errno;
              fwd->fail(err);
 -            comm_close(fd);
 +            conn->close();
-             do_next_read = 0;
          }
-     } else {
-         entry->timestampsSet();
-         entry->flush();
+         return;
+     }
  
-         if (!EBIT_TEST(entry->flags, RELEASE_REQUEST))
-             entry->setPublicKey();
+     if (aBufferLength > 0) {
+         if (!dataWritten)
+             setReplyToOK(entry);
  
-         fwd->complete();
-         debugs(75, 3, "whoisReadReply: Done: " << entry->url()  );
-         conn->close();
-         do_next_read = 0;
-     }
+         kb_incr(&statCounter.server.all.kbytes_in, aBufferLength);
+         kb_incr(&statCounter.server.http.kbytes_in, aBufferLength);
+         /* No range support, we always grab it all */
+         dataWritten = true;
+         entry->append(aBuffer, aBufferLength);
+         entry->flush();
  
-     if (do_next_read) {
 -        comm_read(fd, aBuffer, BUFSIZ, whoisReadReply, this);
 +        AsyncCall::Pointer call = commCbCall(5,4, "whoisReadReply",
 +                                             CommIoCbPtrFun(whoisReadReply, this));
 +        comm_read(conn, aBuffer, BUFSIZ, call);
+         return;
      }
 -    comm_close(fd);
+     /* no bytes read. stop reading */
+     entry->timestampsSet();
+     entry->flush();
+     if (!EBIT_TEST(entry->flags, RELEASE_REQUEST))
+         entry->setPublicKey();
+     fwd->complete();
+     debugs(75, 3, "whoisReadReply: Done: " << entry->url());
++    conn->close();
  }
  
  static void