From: Amos Jeffries Date: Fri, 13 May 2011 08:13:01 +0000 (+1200) Subject: Merge from trunk. Remove dead files and fluff changes X-Git-Tag: take08~55^2~124^2~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1b76e6c1b429e007b8a22af0c5162cac0cb18f2e;p=thirdparty%2Fsquid.git Merge from trunk. Remove dead files and fluff changes --- 1b76e6c1b429e007b8a22af0c5162cac0cb18f2e diff --cc src/CommCalls.cc index ef9456894c,3f7da9996b..bd7e8c4afd --- a/src/CommCalls.cc +++ b/src/CommCalls.cc @@@ -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; } diff --cc src/DelayTagged.cc index a29b749364,a29b749364..5e510a4620 --- a/src/DelayTagged.cc +++ b/src/DelayTagged.cc @@@ -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" diff --cc src/DelayUser.cc index 24c20dc2d4,fbac8e5b3f..818f9beacf --- a/src/DelayUser.cc +++ b/src/DelayUser.cc @@@ -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" diff --cc src/DelayVector.cc index eef4ee6303,eef4ee6303..0f286446a8 --- a/src/DelayVector.cc +++ b/src/DelayVector.cc @@@ -41,6 -41,6 +41,7 @@@ #if USE_DELAY_POOLS #include "squid.h" ++#include "comm/Connection.h" #include "DelayVector.h" #include "CommRead.h" diff --cc src/HttpRequest.cc index d5bdbd3e35,5cfe284de2..f4ce330caf --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@@ -35,14 -35,10 +35,11 @@@ */ #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" diff --cc src/Makefile.am index a85b43551a,0118aa90e8..778c6345fa --- a/src/Makefile.am +++ b/src/Makefile.am @@@ -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 \ @@@ -1103,7 -1149,18 +1156,17 @@@ 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 \ @@@ -2148,26 -2396,55 +2412,54 @@@ 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 \ + cbdata.cc \ + String.cc \ - tests/stub_comm.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) \ + auth/libacls.la \ + ident/libident.la \ - acl/libacls.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) diff --cc src/PeerSelectState.h index 92944f5a72,49e7386c76..b312464450 --- a/src/PeerSelectState.h +++ b/src/PeerSelectState.h @@@ -33,38 -33,10 +33,38 @@@ #ifndef SQUID_PEERSELECTSTATE_H #define SQUID_PEERSELECTSTATE_H +#include "Array.h" #include "cbdata.h" +#include "comm/forward.h" +#include "hier_code.h" - #include "ip/Address.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 { diff --cc src/ProtoPort.h index c21b95b5f6,323a6d2084..42a4a4ea07 --- a/src/ProtoPort.h +++ b/src/ProtoPort.h @@@ -1,3 -1,6 +1,7 @@@ + /* + * $Id$ + */ ++ #ifndef SQUID_PROTO_PORT_H #define SQUID_PROTO_PORT_H diff --cc src/Server.cc index dbee8aca6d,63292c70ad..754fc44957 --- a/src/Server.cc +++ b/src/Server.cc @@@ -33,13 -33,12 +33,13 @@@ */ #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 a314c0419b,c6b9b5c2df..4032ac1568 --- a/src/Server.h +++ b/src/Server.h @@@ -34,7 -34,12 +34,11 @@@ #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" diff --cc src/acl/FilledChecklist.cc index 56b7c55ad9,d85c5387ff..e061e8c638 --- a/src/acl/FilledChecklist.cc +++ b/src/acl/FilledChecklist.cc @@@ -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); diff --cc src/adaptation/icap/Xaction.cc index da21616223,7bd9b31f6b..9cd3ae5ea3 --- a/src/adaptation/icap/Xaction.cc +++ b/src/adaptation/icap/Xaction.cc @@@ -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 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 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(); } diff --cc src/auth/UserRequest.cc index bee0f7346d,f5637e627a..4744e5d0f4 --- a/src/auth/UserRequest.cc +++ b/src/auth/UserRequest.cc @@@ -42,9 -42,12 +42,13 @@@ #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_manager.cc index a4860419b9,7b23c766ce..5f9664432a --- a/src/cache_manager.cc +++ b/src/cache_manager.cc @@@ -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/client_side.cc index e6a4118958,622237fffa..681c4d9cbe --- a/src/client_side.cc +++ b/src/client_side.cc @@@ -84,8 -84,9 +84,10 @@@ #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 @@@ -661,24 -671,23 +666,23 @@@ #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); } + #endif - if (pinning.fd >= 0) - comm_close(pinning.fd); + + if (Comm::IsConnOpen(pinning.serverConnection)) + pinning.serverConnection->close(); + pinning.serverConnection = NULL; + + if (Comm::IsConnOpen(clientConnection)) + clientConnection->close(); + clientConnection = NULL; BodyProducer::swanSong(); flags.swanSang = true; @@@ -1512,14 -1515,13 +1512,13 @@@ voi 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; } @@@ -1533,8 -1535,8 +1532,8 @@@ * 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 @@@ -1561,11 -1563,14 +1560,14 @@@ */ 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(); + } else { + // XXX: Can this happen? CONNECT tunnels have deferredRequest set. - debugs(33, DBG_IMPORTANT, HERE << "abandoning FD " << conn->fd); ++ 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(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; } @@@ -2426,13 -2472,14 +2462,15 @@@ 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(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; } @@@ -2442,18 -2489,19 +2480,21 @@@ 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(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; @@@ -2508,11 -2564,12 +2553,11 @@@ clientStreamNode *node = context->getClientReplyContext(); clientReplyContext *repContext = dynamic_cast(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; } @@@ -2523,10 -2580,10 +2568,10 @@@ 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; } @@@ -2537,10 -2594,11 +2582,11 @@@ clientStreamNode *node = context->getClientReplyContext(); clientReplyContext *repContext = dynamic_cast(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; } } @@@ -2570,9 -2630,10 +2618,10 @@@ 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 */ @@@ -2691,18 -2746,16 +2731,17 @@@ /* 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; } } @@@ -2716,11 -2768,12 +2754,10 @@@ 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) { @@@ -2761,13 -2811,11 +2798,11 @@@ } /* 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 @@@ -2779,9 -2827,9 +2814,9 @@@ /* 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 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 */ @@@ -3162,18 -3225,18 +3197,18 @@@ // 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(); + + // We are going to read new request + flags.readMore = true; - debugs(33, 5, HERE << "converting FD " << fd << " to SSL"); + debugs(33, 5, HERE << "converting " << clientConnection << " to SSL"); return getSslContextStart(); } @@@ -3626,30 -3735,6 +3661,30 @@@ clientHttpsConnectionsOpen(void } #endif +/// 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 ? " intercepted" : "") << - (s->spoof_client_ip ? " spoofing" : "") << - (s->sslBump ? " bumpy" : "") << - (s->accel ? " accelerated" : "") ++ 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 */ } diff --cc src/client_side.h index 24c1104098,dbc8017aeb..aa5961f764 --- a/src/client_side.h +++ b/src/client_side.h @@@ -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); @@@ -160,20 -135,9 +134,7 @@@ }; - /** - * 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_; + // XXX: CBDATA plays with public/private and leaves the following 'private' fields all public... :( + CBDATA_CLASS2(ConnStateData); - bool transparent_; bool closing_; bool switchedToHttps_; diff --cc src/client_side_reply.cc index 0f86bc22c5,2680d1175f..c9a8a58aa9 --- a/src/client_side_reply.cc +++ b/src/client_side_reply.cc @@@ -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); } } diff --cc src/client_side_request.cc index 4d4d540a8d,5d4565b9e1..1a1169ea6b --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@@ -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; diff --cc src/client_side_request.h index 75895b896d,df9252fb40..b1bf1be2ac --- a/src/client_side_request.h +++ b/src/client_side_request.h @@@ -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 cc5dc00474,b92dc8e92f..8e2ccfb8dd --- a/src/comm.cc +++ b/src/comm.cc @@@ -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) @@@ -608,8 -622,6 +592,8 @@@ 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 ¶ms = GetCommParams(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) { + 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 FD " << conn->fd << " with TCP RST: " << xstrerror()); ++ 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; diff --cc src/comm/ConnOpener.cc index 7374b8f1ee,0000000000..b3e952d985 mode 100644,000000..100644 --- a/src/comm/ConnOpener.cc +++ b/src/comm/ConnOpener.cc @@@ -1,327 -1,0 +1,326 @@@ +/* + * DEBUG: section 05 Socket Connection Opener + */ + +#include "config.h" - //#include "base/TextException.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 ¶ms = GetCommParams(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 abortDialer; + calls_.earlyAbort_ = JobCallback(5, 4, abortDialer, this, Comm::ConnOpener::earlyAbort); + comm_add_close_handler(conn_->fd, calls_.earlyAbort_); + + typedef CommCbMemFunT 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(data); + assert(cs); + + // Ew. we are now outside the all AsyncJob protections. + // get back inside by scheduling another call... + typedef NullaryMemFunT 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(data); + assert(cs); + + // Ew. we are now outside the all AsyncJob protections. + // get back inside by scheduling another call... + typedef NullaryMemFunT Dialer; + AsyncCall::Pointer call = JobCallback(5, 4, Dialer, cs, Comm::ConnOpener::connect); + ScheduleCallHere(call); +} diff --cc src/comm/IoCallback.cc index a862cd5426,4026737754..c8806e28da --- a/src/comm/IoCallback.cc +++ b/src/comm/IoCallback.cc @@@ -16,9 -15,9 +16,7 @@@ Comm::CallbackTableInit( iocb_table = static_cast(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; } } diff --cc src/comm/Makefile.am index 0ba83c14ad,cdb8f5032a..2ed340dc9d --- a/src/comm/Makefile.am +++ b/src/comm/Makefile.am @@@ -27,3 -23,3 +27,5 @@@ libcomm_la_SOURCES= Write.h \ \ comm_internal.h ++ ++EXTRA_DIST= stub_libcomm.cc diff --cc src/comm/ModPoll.cc index 095d0b56e4,d4a884d1e0..2f31d99a16 --- a/src/comm/ModPoll.cc +++ b/src/comm/ModPoll.cc @@@ -35,8 -35,8 +35,10 @@@ #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; diff --cc src/comm/ModSelect.cc index a32b47bbc0,a32b47bbc0..d7c773393c --- a/src/comm/ModSelect.cc +++ b/src/comm/ModSelect.cc @@@ -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; diff --cc src/comm/stub_libcomm.cc index 0000000000,0000000000..16a80a30db new file mode 100644 --- /dev/null +++ b/src/comm/stub_libcomm.cc @@@ -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 afc977ddd0,f7b283726d..40936b5324 --- a/src/defines.h +++ b/src/defines.h @@@ -62,14 -62,12 +62,6 @@@ #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) diff --cc src/delay_pools.cc index 566291e816,566291e816..586b4da6b2 --- a/src/delay_pools.cc +++ b/src/delay_pools.cc @@@ -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; diff --cc src/dns_internal.cc index c0df7f66bc,6d8a67474f..e329a9d277 --- a/src/dns_internal.cc +++ b/src/dns_internal.cc @@@ -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 CNCB idnsInitVCConnected; - static IOCB idnsReadVCHeader; +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; + // 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; - commSetConnTimeout(vc->conn, Config.Timeout.idns_query, nil); + - commSetTimeout(vc->fd, timeout, NULL, NULL); ++ commSetConnTimeout(vc->conn, timeout, nil); AsyncCall::Pointer call = commCbCall(78, 5, "idnsSentQueryVC", CommIoCbPtrFun(&idnsSentQueryVC, vc)); diff --cc src/errorpage.cc index 3a42e3ab10,8c8308b802..fabedb95ff --- a/src/errorpage.cc +++ b/src/errorpage.cc @@@ -32,12 -32,13 +32,14 @@@ * */ #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 c50887a072,bd7a52dae7..07c424879d --- a/src/errorpage.h +++ b/src/errorpage.h @@@ -35,9 -35,10 +35,11 @@@ #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 7f0cceb10c,7f0cceb10c..fefca431e6 --- a/src/esi/Esi.cc +++ b/src/esi/Esi.cc @@@ -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(); diff --cc src/eui/Eui48.cc index 72e4909be1,b64cda26a9..b65518f0f7 --- a/src/eui/Eui48.cc +++ b/src/eui/Eui48.cc @@@ -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); diff --cc src/external_acl.cc index d5aab6cb18,c661e5de7f..a52a4ef7f1 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@@ -55,11 -59,8 +59,9 @@@ #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 c6f6022296,d5b29626be..05d7a73498 --- a/src/forward.cc +++ b/src/forward.cc @@@ -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) @@@ -400,13 -375,31 +391,14 @@@ 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()) @@@ -814,10 -861,10 +818,9 @@@ 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; } @@@ -866,23 -901,107 +869,23 @@@ 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 d6a55fb29c,5858e024d3..f0579736d4 --- a/src/ftp.cc +++ b/src/ftp.cc @@@ -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/gopher.cc index 7f112e7294,fa78bf26e6..605074e80a --- a/src/gopher.cc +++ b/src/gopher.cc @@@ -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++) @@@ -832,18 -831,17 +832,19 @@@ 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. */ @@@ -854,24 -852,15 +855,17 @@@ 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 c3165f02b4,fe129889a6..9099fd9fe7 --- a/src/helper.cc +++ b/src/helper.cc @@@ -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; } @@@ -884,37 -881,29 +881,32 @@@ 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 7ebb2ba13d,a5dac22325..7d40becbce --- a/src/helper.h +++ b/src/helper.h @@@ -35,9 -35,8 +35,9 @@@ #include "squid.h" #include "cbdata.h" +#include "comm/forward.h" - #include "HelperChildConfig.h" #include "ip/Address.h" + #include "HelperChildConfig.h" class helper_request; diff --cc src/http.cc index dd46bbb226,17bbbc3003..fc0b4b8538 --- a/src/http.cc +++ b/src/http.cc @@@ -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 %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) { @@@ -1110,8 -1111,9 +1111,9 @@@ 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 2c6549adcc,990d72e0ec..2f0aa72daa --- a/src/icp_v2.cc +++ b/src/icp_v2.cc @@@ -36,15 -36,18 +36,19 @@@ */ #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); diff --cc src/ip/Intercept.cc index d0d25fc0d7,602ce22261..3a9837d861 --- a/src/ip/Intercept.cc +++ b/src/ip/Intercept.cc @@@ -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 b52a99dd3f,11b5f362ba..7d7c4a9e35 --- a/src/ip/Qos.cci +++ b/src/ip/Qos.cci @@@ -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 } diff --cc src/ipc/Coordinator.cc index 9bab7cc3ce,02656fee3d..c6948c6aa6 --- a/src/ipc/Coordinator.cc +++ b/src/ipc/Coordinator.cc @@@ -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); } + #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 + -int +Comm::ConnectionPointer Ipc::Coordinator::openListenSocket(const SharedListenRequest& request, int &errNo) { diff --cc src/ipc/Coordinator.h index 3937cd387f,bc0d8fd765..d81a04fe4b --- a/src/ipc/Coordinator.h +++ b/src/ipc/Coordinator.h @@@ -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 diff --cc src/ipc/Forwarder.cc index 0000000000,3650229a2d..0d1de0f916 mode 000000,100644..100644 --- a/src/ipc/Forwarder.cc +++ b/src/ipc/Forwarder.cc @@@ -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 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(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); + } diff --cc src/ipc/Forwarder.h index 0000000000,25b115b020..dfda91f6e7 mode 000000,100644..100644 --- a/src/ipc/Forwarder.h +++ b/src/ipc/Forwarder.h @@@ -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 + + + 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 RequestsMap; + static RequestsMap TheRequestsMap; ///< pending Coordinator requests + + static unsigned int LastRequestId; ///< last requestId used + + CBDATA_CLASS2(Forwarder); + }; + + } // namespace Ipc + + #endif /* SQUID_IPC_FORWARDER_H */ diff --cc src/ipc/Inquirer.cc index 0000000000,d80dce5e3a..22c03a2d6a mode 000000,100644..100644 --- a/src/ipc/Inquirer.cc +++ b/src/ipc/Inquirer.cc @@@ -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 + + + 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(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(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 1b02099a6a,e4a4ab33b7..fb2fb73d8c --- a/src/ipc/Port.cc +++ b/src/ipc/Port.cc @@@ -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"; diff --cc src/ipc/SharedListen.cc index d39f829aae,6b76b96acf..25451ef94b --- a/src/ipc/SharedListen.cc +++ b/src/ipc/SharedListen.cc @@@ -6,9 -6,9 +6,10 @@@ */ #include "config.h" - #include "base/TextException.h" + #include #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 -- /// holds information necessary to handle JoinListen response class PendingOpenRequest { diff --cc src/ipc/StartListening.h index 0604dc95d6,99354133b4..df4f12d840 --- a/src/ipc/StartListening.h +++ b/src/ipc/StartListening.h @@@ -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 diff --cc src/ipc/UdsOp.cc index 58f65ee5fb,af7edc2b73..7230e37b34 --- a/src/ipc/UdsOp.cc +++ b/src/ipc/UdsOp.cc @@@ -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) ++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); - if (getsockname(fd, reinterpret_cast(&addr), &len) == 0) { - Ip::Address ipAddr(addr); ++ if (getsockname(conn->fd, reinterpret_cast(&addr), &len) == 0) { ++ conn->remote = addr; + struct addrinfo* addr_info = NULL; - ipAddr.GetAddrInfo(addr_info); ++ conn->remote.GetAddrInfo(addr_info); + addr_info->ai_socktype = socktype; + addr_info->ai_protocol = protocol; - comm_import_opened(fd, ipAddr, COMM_NONBLOCKING, Ipc::FdNote(noteId), addr_info); - ipAddr.FreeAddrInfo(addr_info); ++ comm_import_opened(conn, Ipc::FdNote(noteId), addr_info); ++ conn->remote.FreeAddrInfo(addr_info); + } else { - debugs(54, DBG_CRITICAL, HERE << "ERROR: FD " << fd << ' ' << xstrerror()); - ::close(fd); - fd = -1; ++ debugs(54, DBG_CRITICAL, "ERROR: Ipc::ImportFdIntoComm: " << conn << ' ' << xstrerror()); ++ conn->close(); + } - return fd; ++ return conn; + } diff --cc src/ipc/UdsOp.h index 87667146c9,bea34d3a6e..e66a7785fb --- a/src/ipc/UdsOp.h +++ b/src/ipc/UdsOp.h @@@ -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); + /// import socket fd from another strand into our Comm state -int ImportFdIntoComm(int fd, int socktype, int protocol, FdNoteId noteId); ++const Comm::ConnectionPointer & ImportFdIntoComm(const Comm::ConnectionPointer &conn, int socktype, int protocol, FdNoteId noteId); } diff --cc src/main.cc index f2d1aac786,67e110fee9..485f1726bb --- a/src/main.cc +++ b/src/main.cc @@@ -34,20 -34,12 +34,20 @@@ #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" @@@ -62,23 -54,28 +62,30 @@@ #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 diff --cc src/mgr/Action.cc index 5adce85264,5adce85264..5fa0e4ba79 --- a/src/mgr/Action.cc +++ b/src/mgr/Action.cc @@@ -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); } diff --cc src/mgr/Forwarder.cc index fdec19287a,4ea3f8d34e..29e4d289d5 --- a/src/mgr/Forwarder.cc +++ b/src/mgr/Forwarder.cc @@@ -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" @@@ -22,27 -21,24 +22,24 @@@ 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(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() @@@ -60,15 -55,16 +56,16 @@@ /// 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"); } diff --cc src/mgr/Forwarder.h index f3cf15d87d,1c8b9e84f5..473c543238 --- a/src/mgr/Forwarder.h +++ b/src/mgr/Forwarder.h @@@ -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 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 RequestsMap; - static RequestsMap TheRequestsMap; ///< pending Coordinator requests - - static unsigned int LastRequestId; ///< last requestId used - CBDATA_CLASS2(Forwarder); }; diff --cc src/mgr/FunAction.cc index 05d1129ca3,6fd0f97c1a..b236842a5e --- a/src/mgr/FunAction.cc +++ b/src/mgr/FunAction.cc @@@ -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 diff --cc src/mgr/InfoAction.cc index 17ec7590cc,eb5760ba0b..6e051141fc --- a/src/mgr/InfoAction.cc +++ b/src/mgr/InfoAction.cc @@@ -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 diff --cc src/mgr/Inquirer.cc index e6e873b0d1,09c0bfd30e..4f611dd966 --- a/src/mgr/Inquirer.cc +++ b/src/mgr/Inquirer.cc @@@ -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" @@@ -25,48 -26,28 +27,29 @@@ 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(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 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 replyBuf(reply->pack()); + std::auto_ptr 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 reply(err->BuildHttpReply()); + replyBuf.reset(reply->pack()); + errorStateFree(err); + } else { + std::auto_ptr 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(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(*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 diff --cc src/mgr/Inquirer.h index 8108713327,c8e6cc8673..6d9bcd6b3e --- a/src/mgr/Inquirer.h +++ b/src/mgr/Inquirer.h @@@ -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 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 RequestsMap; - static RequestsMap TheRequestsMap; ///< pending strand requests - - static unsigned int LastRequestId; ///< last requestId used CBDATA_CLASS2(Inquirer); }; diff --cc src/mgr/Request.cc index 045ea9b45a,9e6f76e834..bf99adf361 --- a/src/mgr/Request.cc +++ b/src/mgr/Request.cc @@@ -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); } diff --cc src/mgr/Request.h index e85f37dcab,50b29d7016..45431d3249 --- a/src/mgr/Request.h +++ b/src/mgr/Request.h @@@ -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 }; diff --cc src/mgr/StoreToCommWriter.cc index 12dfce29ef,52aed325d8..ce579052fc --- a/src/mgr/StoreToCommWriter.cc +++ b/src/mgr/StoreToCommWriter.cc @@@ -160,29 -161,6 +160,6 @@@ voi Mgr::StoreToCommWriter::Abort(void* param) { StoreToCommWriter* mgrWriter = static_cast(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(&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; - } diff --cc src/multicast.cc index e00b73aa11,c8f273847f..dcb30c55b2 --- a/src/multicast.cc +++ b/src/multicast.cc @@@ -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; } @@@ -70,16 -73,19 +72,16 @@@ 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 diff --cc src/pconn.cc index 9d05052305,99bf06a9e9..ca23bceeec --- a/src/pconn.cc +++ b/src/pconn.cc @@@ -33,12 -33,11 +33,12 @@@ */ #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 */ diff --cc src/peer_select.cc index cc106f60d5,8715991aad..a8200c304a --- a/src/peer_select.cc +++ b/src/peer_select.cc @@@ -33,18 -33,17 +33,18 @@@ */ #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/redirect.cc index a3cafe26c1,98e56d6422..05f0b331bf --- a/src/redirect.cc +++ b/src/redirect.cc @@@ -34,8 -34,9 +34,10 @@@ */ #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 @@@ -168,14 -177,45 +178,46 @@@ 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(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); } diff --cc src/snmp/Forwarder.cc index 0000000000,66f6f711bd..87b0aea5b0 mode 000000,100644..100644 --- a/src/snmp/Forwarder.cc +++ b/src/snmp/Forwarder.cc @@@ -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(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(*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(*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); + } diff --cc src/snmp/Inquirer.cc index 0000000000,6d748b0355..4f19e60c1b mode 000000,100644..100644 --- a/src/snmp/Inquirer.cc +++ b/src/snmp/Inquirer.cc @@@ -1,0 -1,102 +1,107 @@@ + /* + * $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), - aggrPdu(aRequest.pdu), - fd(ImportFdIntoComm(aRequest.fd, SOCK_DGRAM, IPPROTO_UDP, Ipc::fdnInSnmpSocket)) ++ 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(this, &Inquirer::noteCommClosed)); - comm_add_close_handler(fd, closer); ++ comm_add_close_handler(conn->fd, closer); + } + + /// closes our copy of the client connection socket + void + Snmp::Inquirer::cleanup() + { - if (fd >= 0) { ++ if (Comm::IsConnOpen(conn)) { + if (closer != NULL) { - comm_remove_close_handler(fd, closer); ++ comm_remove_close_handler(conn->fd, closer); + closer = NULL; + } - comm_close(fd); - fd = -1; ++ conn->close(); + } ++ conn = NULL; + } + + void + Snmp::Inquirer::start() + { + debugs(49, 5, HERE); + Ipc::Inquirer::start(); - Must(fd >= 0); ++ 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(*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); - Must(fd < 0 || fd == params.fd); - fd = -1; ++ 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(*request); + snmp_build(&req.session, &aggrPdu, buffer, &len); - comm_udp_sendto(fd, req.address, buffer, len); ++ comm_udp_sendto(conn->fd, req.address, buffer, len); + } diff --cc src/snmp/Inquirer.h index 0000000000,5efcdcfee7..e9990a34b3 mode 000000,100644..100644 --- a/src/snmp/Inquirer.h +++ b/src/snmp/Inquirer.h @@@ -1,0 -1,54 +1,55 @@@ + /* + * $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 - int fd; ///< client connection descriptor ++ 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 */ diff --cc src/snmp_core.cc index 28e7f25ed0,fb300d2ed2..6c92a749d6 --- a/src/snmp_core.cc +++ b/src/snmp_core.cc @@@ -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 ca5587aa96,284902e5eb..2ce506f573 --- a/src/snmp_core.h +++ b/src/snmp_core.h @@@ -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 */ diff --cc src/ssl/Makefile.am index 6eb6756a66,6eb6756a66..48f80c7fca --- a/src/ssl/Makefile.am +++ b/src/ssl/Makefile.am @@@ -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 = \ diff --cc src/ssl/stub_libsslsquid.cc index 0000000000,0000000000..8c15b88905 new file mode 100644 --- /dev/null +++ b/src/ssl/stub_libsslsquid.cc @@@ -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) diff --cc src/ssl/stub_libsslutil.cc index 0000000000,0000000000..5ecf4af91c new file mode 100644 --- /dev/null +++ b/src/ssl/stub_libsslutil.cc @@@ -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 a4fe88811e,a1413ee2c6..31eaa1e9df --- a/src/stat.cc +++ b/src/stat.cc @@@ -35,8 -35,10 +35,11 @@@ #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 f0e182bdd6,a9d24db0d9..d574fecb91 --- a/src/store.cc +++ b/src/store.cc @@@ -34,27 -34,25 +34,27 @@@ */ #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/tests/stub_client_db.cc index 7c74942032,0000000000..c2359e84f2 mode 100644,000000..100644 --- a/src/tests/stub_client_db.cc +++ b/src/tests/stub_client_db.cc @@@ -1,68 -1,0 +1,68 @@@ +#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, protocol_t, size_t) ++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"); +} diff --cc src/tests/stub_comm.cc index 60b3ef9683,a2007ae538..07031e57a1 --- a/src/tests/stub_comm.cc +++ b/src/tests/stub_comm.cc @@@ -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) { diff --cc src/tests/stub_icp.cc index 0000000000,0000000000..3fa18773c9 new file mode 100644 --- /dev/null +++ b/src/tests/stub_icp.cc @@@ -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) diff --cc src/tests/stub_ipc.cc index 0000000000,0000000000..57b93b7a9f new file mode 100644 --- /dev/null +++ b/src/tests/stub_ipc.cc @@@ -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; ++} diff --cc src/tests/stub_store.cc index 9832a53f9f,5914ed0592..3ec3774e0a --- a/src/tests/stub_store.cc +++ b/src/tests/stub_store.cc @@@ -1,53 -1,130 +1,130 @@@ - /* - * $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 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 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) 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 27671f8097,e98d4e7ded..878fbd97a5 --- a/src/tools.cc +++ b/src/tools.cc @@@ -33,14 -33,13 +33,11 @@@ */ #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 */ + // clear both http_port and https_port lists. - for (int i = 0; i < NHttpSockets; i++) { + for (i = 0; i < NHttpSockets; i++) { if (HttpSockets[i] >= 0) close(HttpSockets[i]); } diff --cc src/tunnel.cc index f5173c678c,2317ed027c..50e5bde4d4 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@@ -33,23 -34,20 +34,23 @@@ */ #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 "http.h" -#include "ip/tools.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", @@@ -330,25 -333,24 +333,23 @@@ /* 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; } @@@ -379,11 -381,12 +380,11 @@@ /* 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); } +/** + * All the pieces we need to write to client and/or server connection - * Have been written. Start the blind pump. ++ * 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(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 %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); } + 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 = 1; ++ 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 14d5809c55,87e16d7c3e..9ffa37cec2 --- a/src/typedefs.h +++ b/src/typedefs.h @@@ -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/wccp.cc index 414d9b9a46,fdad1a0a82..389624756e --- a/src/wccp.cc +++ b/src/wccp.cc @@@ -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 f0a4326f92,f7ef8227c5..56ed18c5e5 --- a/src/whois.cc +++ b/src/whois.cc @@@ -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; } + + /* 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()); - comm_close(fd); ++ conn->close(); } static void