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;
}
#if USE_DELAY_POOLS
#include "squid.h"
++#include "comm/Connection.h"
#include "DelayTagged.h"
#include "NullDelayId.h"
#include "Store.h"
#include "DelayUser.h"
#include "auth/UserRequest.h"
#include "auth/User.h"
++#include "comm/Connection.h"
#include "NullDelayId.h"
#include "Store.h"
#if USE_DELAY_POOLS
#include "squid.h"
++#include "comm/Connection.h"
#include "DelayVector.h"
#include "CommRead.h"
*/
#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"
if ENABLE_SSL
SUBDIRS += ssl
SSL_LIBS = \
-- ssl/libsslutil.la \
-- ssl/libsslsquid.la
++ ssl/libsslsquid.la \
++ ssl/libsslutil.la
else
SSL_LOCAL_LIBS =
endif
## Packer.cc \
## StatHist.cc \
## String.cc \
++##
++## disk.cc \
++## fs/libfs.la \
tests_testACLMaxUserIP_SOURCES= \
cbdata.cc \
ClientInfo.h \
+ ConfigOption.cc \
ConfigParser.cc \
- disk.cc \
+ DiskIO/ReadRequest.cc \
+ DiskIO/WriteRequest.cc \
ETag.cc \
+ event.cc \
+ filemap.cc \
HelperChildConfig.h \
HelperChildConfig.cc \
HttpHeader.cc \
nodist_tests_testACLMaxUserIP_SOURCES= \
$(TESTSOURCES)
tests_testACLMaxUserIP_LDADD= \
- $(COMMON_LIBS) \
+ $(AUTH_ACL_LIBS) \
+ ident/libident.la \
+ acl/libacls.la \
+ eui/libeui.la \
+ acl/libstate.la \
+ $(AUTH_LIBS) \
+ acl/libapi.la \
+ anyp/libanyp.la \
+ base/libbase.la \
+ libsquid.la \
+ ip/libip.la \
- fs/libfs.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
$(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)
$(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 \
tests_testString_DEPENDENCIES = \
$(SQUID_CPPUNIT_LA)
- SWAP_TEST_SOURCES = \
- CacheDigest.cc \
- cbdata.cc \
- ClientInfo.h \
- ConfigOption.cc \
- ConfigParser.cc \
- disk.cc \
- ETag.cc \
- EventLoop.cc \
+ SWAP_TEST_DS =\
+ repl_modules.o \
+ $(DISK_LIBS) \
+ $(AUTH_ACL_LIBS) \
+ ident/libident.la \
+ acl/libacls.la \
+ eui/libeui.la \
+ acl/libstate.la \
+ $(AUTH_LIBS) \
+ acl/libapi.la \
+ base/libbase.la \
+ libsquid.la \
+ ip/libip.la \
+ fs/libfs.la \
+ ipc/libipc.la \
+ mgr/libmgr.la \
+ $(REPL_OBJS) \
+ $(SQUID_CPPUNIT_LA)
+
+ tests_testUfs_SOURCES = \
+ tests/testUfs.cc \
+ tests/testMain.cc \
+ tests/testUfs.h \
+ tests/stub_cache_manager.cc \
++ tests/stub_client_db.cc \
+ tests/stub_HelperChildConfig.cc \
++ tests/stub_icp.cc \
++ tests/stub_ipc.cc \
++ tests/stub_pconn.cc \
+ tests/stub_Port.cc \
+ tests/stub_TypedMsgHdr.cc \
+ tests/stub_UdsOp.cc \
+ tests/stub_internal.cc \
- tests/stub_CommIO.cc \
+ tests/stub_store_rebuild.cc \
fd.cc \
+ disk.cc \
filemap.cc \
HttpBody.cc \
- HttpHdrContRange.cc \
- HttpHdrCc.cc \
- HttpHdrSc.cc \
- HttpHdrScTarget.cc \
- HttpHdrRange.cc \
- HttpHeaderTools.cc \
- HttpHeader.cc \
- HttpMsg.cc \
HttpReply.cc \
- HttpRequestMethod.cc \
HttpStatusLine.cc \
int.cc \
list.cc \
StoreMetaVary.cc \
StoreFileSystem.cc \
store_io.cc \
- store_key_md5.cc \
store_swapout.cc \
store_swapmeta.cc \
+ $(UNLINKDSOURCE) \
+ $(WIN32_SOURCE) \
+ event.cc \
+ $(DELAY_POOL_SOURCE) \
+ CacheDigest.cc \
+ ConfigParser.cc \
+ EventLoop.cc \
+ HttpMsg.cc \
+ RemovalPolicy.cc \
store_dir.cc \
store.cc \
- String.cc \
+ HttpRequestMethod.cc \
+ store_key_md5.cc \
+ Parsing.cc \
+ ConfigOption.cc \
SwapDir.cc \
- tests/stub_access_log.cc \
tests/stub_acl.cc \
tests/stub_cache_cf.cc \
- tests/stub_client_side_request.cc \
- tests/stub_debug.cc \
- tests/stub_errorpage.cc \
tests/stub_helper.cc \
- tests/stub_comm.cc \
+ cbdata.cc \
+ String.cc \
+ tests/stub_debug.cc \
+ tests/stub_client_side_request.cc \
tests/stub_http.cc \
- tests/stub_HttpRequest.cc \
- tests/stub_internal.cc \
+ mem_node.cc \
+ stmem.cc \
tests/stub_mime.cc \
+ HttpHeaderTools.cc \
+ HttpHeader.cc \
+ mem.cc \
+ ClientInfo.h \
+ MemBuf.cc \
+ HttpHdrContRange.cc \
+ Packer.cc \
+ HttpHdrCc.cc \
+ HttpHdrSc.cc \
+ HttpHdrScTarget.cc \
+ url.cc \
+ StatHist.cc \
+ HttpHdrRange.cc \
+ ETag.cc \
+ tests/stub_errorpage.cc \
+ tests/stub_HttpRequest.cc \
+ tests/stub_access_log.cc \
+ refresh.cc \
tests/stub_store_client.cc \
- tests/stub_store_rebuild.cc \
tests/stub_tools.cc \
tests/testStoreSupport.cc \
tests/testStoreSupport.h \
SquidMath.h \
swap_log_op.cc
tests_testUfs_LDADD = \
- anyp/libanyp.la \
CommCalls.o \
DnsLookupDetails.o \
+ $(AUTH_ACL_LIBS) \
+ ident/libident.la \
+ acl/libacls.la \
+ eui/libeui.la \
+ acl/libstate.la \
+ $(AUTH_LIBS) \
+ acl/libapi.la \
+ base/libbase.la \
+ libsquid.la \
+ ip/libip.la \
+ fs/libfs.la \
+ ipc/libipc.la \
+ mgr/libmgr.la \
$(REPL_OBJS) \
++ acl/libacls.la \
++ anyp/libanyp.la \
$(DISK_LIBS) \
$(DISK_OS_LIBS) \
- acl/libacls.la \
+ auth/libacls.la \
+ ident/libident.la \
+ eui/libeui.la \
+ acl/libstate.la \
+ auth/libauth.la \
acl/libapi.la \
- libsquid.la \
- base/libbase.la \
- ip/libip.la \
+ fs/libfs.la \
+ ipc/libipc.la \
+ mgr/libmgr.la \
++ libsquid.la \
++ $(SSL_LIBS) \
++ comm/libcomm.la \
++ base/libbase.la \
++ ip/libip.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
$(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)
#ifndef SQUID_PEERSELECTSTATE_H
#define SQUID_PEERSELECTSTATE_H
+#include "Array.h"
#include "cbdata.h"
- #include "ip/Address.h"
+#include "comm/forward.h"
+#include "hier_code.h"
#include "PingData.h"
+ #include "ip/Address.h"
+class HttpRequest;
+class StoreEntry;
+
+typedef void PSC(Comm::ConnectionList *, void *);
+
+SQUIDCEXTERN void peerSelect(Comm::ConnectionList *, HttpRequest *, StoreEntry *, PSC *, void *data);
+SQUIDCEXTERN void peerSelectInit(void);
+
+/**
+ * A peer which has been selected as a possible destination.
+ * Listed as pointers here so as to prevent duplicates being added but will
+ * be converted to a set of IP address path options before handing back out
+ * to the caller.
+ *
+ * Certain connection flags and outgoing settings will also be looked up and
+ * set based on the received request and peer settings before handing back.
+ */
+class FwdServer
+{
+public:
+ peer *_peer; /* NULL --> origin server */
+ hier_code code;
+ FwdServer *next;
+};
+
class ps_state
{
+ /*
+ * $Id$
+ */
++
#ifndef SQUID_PROTO_PORT_H
#define SQUID_PROTO_PORT_H
*/
#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"
#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"
#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);
}
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.
void Adaptation::Icap::Xaction::scheduleWrite(MemBuf &buf)
{
+ Must(haveConnection());
+
// comm module will free the buffer
typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommIoCbParams> Dialer;
- writer = JobCallback(93, 3, Dialer, this, Adaptation::Icap::Xaction::noteCommWrote);
- writer = JobCallback(93,3,
++ writer = JobCallback(93, 3,
+ Dialer, this, Adaptation::Icap::Xaction::noteCommWrote);
+
Comm::Write(connection, &buf, writer);
updateTimeout();
}
* here instead of reading directly into readBuf.buf.
*/
typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommIoCbParams> Dialer;
- reader = JobCallback(93, 3, Dialer, this, Adaptation::Icap::Xaction::noteCommRead);
- reader = JobCallback(93,3,
++ reader = JobCallback(93, 3,
+ Dialer, this, Adaptation::Icap::Xaction::noteCommRead);
+
comm_read(connection, commBuf, readBuf.spaceSize(), reader);
updateTimeout();
}
#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"
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 '" <<
}
}
--/**
-- \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)
{
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;
}
#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"
/* 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
void
ClientHttpRequest::logRequest()
{
- if (out.size || logType) {
- al.icp.opcode = ICP_INVALID;
- al.url = log_uri;
- debugs(33, 9, "clientLogRequest: al.url='" << al.url << "'");
-
- if (al.reply) {
- al.http.code = al.reply->sline.status;
- al.http.content_type = al.reply->content_type.termedBuf();
- } else if (loggingEntry() && loggingEntry()->mem_obj) {
- al.http.code = loggingEntry()->mem_obj->getReply()->sline.status;
- al.http.content_type = loggingEntry()->mem_obj->getReply()->content_type.termedBuf();
- }
+ if (!out.size && !logType)
+ debugs(33, 5, HERE << "logging half-baked transaction: " << log_uri);
- debugs(33, 9, "clientLogRequest: http.code='" << al.http.code << "'");
+ al.icp.opcode = ICP_INVALID;
+ al.url = log_uri;
+ debugs(33, 9, "clientLogRequest: al.url='" << al.url << "'");
- if (loggingEntry() && loggingEntry()->mem_obj)
- al.cache.objectSize = loggingEntry()->contentLen();
+ if (al.reply) {
+ al.http.code = al.reply->sline.status;
+ al.http.content_type = al.reply->content_type.termedBuf();
+ } else if (loggingEntry() && loggingEntry()->mem_obj) {
+ al.http.code = loggingEntry()->mem_obj->getReply()->sline.status;
+ al.http.content_type = loggingEntry()->mem_obj->getReply()->content_type.termedBuf();
+ }
- al.cache.caddr.SetNoAddr();
+ debugs(33, 9, "clientLogRequest: http.code='" << al.http.code << "'");
- if (getConn() != NULL) al.cache.caddr = getConn()->log_addr;
+ if (loggingEntry() && loggingEntry()->mem_obj)
+ al.cache.objectSize = loggingEntry()->contentLen();
- al.cache.requestSize = req_sz;
- al.cache.requestHeadersSize = req_sz;
+ al.cache.caddr.SetNoAddr();
- al.cache.replySize = out.size;
- al.cache.replyHeadersSize = out.headers_sz;
+ if (getConn() != NULL) al.cache.caddr = getConn()->log_addr;
- al.cache.highOffset = out.offset;
+ al.cache.requestSize = req_sz;
+ al.cache.requestHeadersSize = req_sz;
- al.cache.code = logType;
+ al.cache.replySize = out.size;
+ al.cache.replyHeadersSize = out.headers_sz;
- al.cache.msec = tvSubMsec(start_time, current_time);
+ al.cache.highOffset = out.offset;
- if (request)
- prepareLogWithRequestDetails(request, &al);
+ al.cache.code = logType;
+
+ al.cache.msec = tvSubMsec(start_time, current_time);
+
+ if (request)
+ prepareLogWithRequestDetails(request, &al);
- if (getConn() != NULL && getConn()->clientConnection != NULL && getConn()->clientConnection->rfc931[0])
- al.cache.rfc931 = getConn()->clientConnection->rfc931;
- if (getConn() != NULL && getConn()->rfc931[0])
- al.cache.rfc931 = getConn()->rfc931;
++ if (getConn() != NULL && getConn()->clientConnection != NULL && getConn()->clientConnection->rfc931[0])
++ al.cache.rfc931 = getConn()->clientConnection->rfc931;
#if USE_SSL && 0
#endif
- ACLFilledChecklist *checklist = clientAclChecklistCreate(Config.accessList.log, this);
-
- if (al.reply)
- checklist->reply = HTTPMSGLOCK(al.reply);
+ ACLFilledChecklist *checklist = clientAclChecklistCreate(Config.accessList.log, this);
- if (!Config.accessList.log || checklist->fastCheck()) {
- if (request)
- al.adapted_request = HTTPMSGLOCK(request);
- accessLogLog(&al, checklist);
- updateCounters();
+ if (al.reply)
+ checklist->reply = HTTPMSGLOCK(al.reply);
- if (getConn() != NULL && getConn()->clientConnection != NULL)
- clientdbUpdate(getConn()->clientConnection->remote, logType, PROTO_HTTP, out.size);
- }
+ if (!Config.accessList.log || checklist->fastCheck()) {
+ if (request)
+ al.adapted_request = HTTPMSGLOCK(request);
+ accessLogLog(&al, checklist);
+ updateCounters();
- delete checklist;
- if (getConn() != NULL)
- clientdbUpdate(getConn()->peer, logType, AnyP::PROTO_HTTP, out.size);
++ if (getConn() != NULL && getConn()->clientConnection != NULL)
++ clientdbUpdate(getConn()->clientConnection->remote, logType, AnyP::PROTO_HTTP, out.size);
}
+ delete checklist;
+
accessLogFreeMemory(&al);
}
void
ConnStateData::swanSong()
{
- debugs(33, 2, "ConnStateData::swanSong: FD " << fd);
- fd = -1;
+ debugs(33, 2, HERE << clientConnection);
- flags.readMoreRequests = false;
+ flags.readMore = false;
- clientdbEstablished(peer, -1); /* decrement */
+ clientdbEstablished(clientConnection->remote, -1); /* decrement */
assert(areAllContextsForThisConnection());
freeAllContexts();
-
+ #if USE_AUTH
if (auth_user_request != NULL) {
debugs(33, 4, "ConnStateData::swanSong: freeing auth_user_request '" << auth_user_request << "' (this is '" << this << "')");
auth_user_request->onConnectionClose(this);
}
- if (pinning.fd >= 0)
- comm_close(pinning.fd);
+ #endif
+
+ if (Comm::IsConnOpen(pinning.serverConnection))
+ pinning.serverConnection->close();
+ pinning.serverConnection = NULL;
+
+ if (Comm::IsConnOpen(clientConnection))
+ clientConnection->close();
+ clientConnection = NULL;
BodyProducer::swanSong();
flags.swanSang = true;
ClientSocketContext::keepaliveNextRequest()
{
ConnStateData * conn = http->getConn();
- bool do_next_read = false;
- debugs(33, 3, "ClientSocketContext::keepaliveNextRequest: FD " << conn->fd);
+ debugs(33, 3, HERE << "ConnnStateData(" << conn->clientConnection << "), Context(" << clientConnection << ")");
connIsFinished();
- if (conn->pinning.pinned && conn->pinning.fd == -1) {
- debugs(33, 2, "clientKeepaliveNextRequest: FD " << conn->fd << " Connection was pinned but server side gone. Terminating client connection");
- comm_close(conn->fd);
+ if (conn->pinning.pinned && !Comm::IsConnOpen(conn->pinning.serverConnection)) {
+ debugs(33, 2, HERE << conn->clientConnection << " Connection was pinned but server side gone. Terminating client connection");
+ conn->clientConnection->close();
return;
}
* from our read buffer we may never re-register for another client read.
*/
- if (clientParseRequest(conn, do_next_read)) {
+ if (conn->clientParseRequests()) {
- debugs(33, 3, "clientSocketContext::keepaliveNextRequest: FD " << conn->fd << ": parsed next request from buffer");
+ debugs(33, 3, HERE << conn->clientConnection << ": parsed next request from buffer");
}
/** \par
*/
if ((deferredRequest = conn->getCurrentContext()).getRaw()) {
- debugs(33, 3, "ClientSocketContext:: FD " << conn->fd << ": calling PushDeferredIfNeeded");
+ debugs(33, 3, HERE << conn->clientConnection << ": calling PushDeferredIfNeeded");
ClientSocketContextPushDeferredIfNeeded(deferredRequest, conn);
- } else {
+ } else if (conn->flags.readMore) {
- debugs(33, 3, "ClientSocketContext:: FD " << conn->fd << ": calling conn->readNextRequest()");
+ debugs(33, 3, HERE << conn->clientConnection << ": calling conn->readNextRequest()");
conn->readNextRequest();
- debugs(33, DBG_IMPORTANT, HERE << "abandoning FD " << conn->fd);
+ } else {
+ // XXX: Can this happen? CONNECT tunnels have deferredRequest set.
++ debugs(33, DBG_IMPORTANT, HERE << "abandoning " << conn->clientConnection);
}
}
/* 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 << "'");
}
}
}
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;
}
if ((request = HttpRequest::CreateFromUrlAndMethod(http->uri, method)) == NULL) {
clientStreamNode *node = context->getClientReplyContext();
debugs(33, 5, "Invalid URL: " << http->uri);
+ // setLogUri should called before repContext->setReplyToError
+ setLogUri(http, http->uri, true);
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL);
+ repContext->setReplyToError(ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, conn->clientConnection->remote, NULL, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
- conn->flags.readMoreRequests = false;
+ conn->flags.readMore = false;
goto finish;
}
clientStreamNode *node = context->getClientReplyContext();
debugs(33, 5, "Unsupported HTTP version discovered. :\n" << HttpParserHdrBuf(hp));
+ // setLogUri should called before repContext->setReplyToError
+ setLogUri(http, http->uri, true);
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_UNSUP_HTTPVERSION, HTTP_HTTP_VERSION_NOT_SUPPORTED, method, http->uri, conn->peer, NULL, HttpParserHdrBuf(hp), NULL);
+ repContext->setReplyToError(ERR_UNSUP_HTTPVERSION, HTTP_HTTP_VERSION_NOT_SUPPORTED, method, http->uri,
+ conn->clientConnection->remote, NULL, HttpParserHdrBuf(hp), NULL);
assert(context->http->out.offset == 0);
context->pullData();
- conn->flags.readMoreRequests = false;
+ conn->flags.readMore = false;
goto finish;
}
if (http_ver.major >= 1 && !request->parseHeader(HttpParserHdrBuf(hp), HttpParserHdrSz(hp))) {
clientStreamNode *node = context->getClientReplyContext();
debugs(33, 5, "Failed to parse request headers:\n" << HttpParserHdrBuf(hp));
+ // setLogUri should called before repContext->setReplyToError
+ setLogUri(http, http->uri, true);
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL);
+ repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri, conn->clientConnection->remote, NULL, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
- conn->flags.readMoreRequests = false;
+ conn->flags.readMore = false;
goto finish;
}
+ request->clientConnectionManager = conn;
+
request->flags.accelerated = http->flags.accel;
+ request->flags.sslBumped = conn->switchedToHttps();
request->flags.ignore_cc = conn->port->ignore_cc;
request->flags.no_direct = request->flags.accelerated ? !conn->port->allow_direct : 0;
clientStreamNode *node = context->getClientReplyContext();
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_UNSUP_REQ,
- HTTP_NOT_IMPLEMENTED, request->method, NULL,
- conn->peer, request, NULL, NULL);
+ repContext->setReplyToError(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED, request->method, NULL,
+ conn->clientConnection->remote, request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
- conn->flags.readMoreRequests = false;
+ conn->flags.readMore = false;
goto finish;
}
assert (repContext);
repContext->setReplyToError(ERR_INVALID_REQ,
HTTP_LENGTH_REQUIRED, request->method, NULL,
- conn->peer, request, NULL, NULL);
+ conn->clientConnection->remote, request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
- conn->flags.readMoreRequests = false;
+ conn->flags.readMore = false;
goto finish;
}
clientStreamNode *node = context->getClientReplyContext();
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
assert (repContext);
- repContext->setReplyToError(ERR_INVALID_REQ, HTTP_EXPECTATION_FAILED, request->method,
- http->uri, conn->peer, request, NULL, NULL);
+ repContext->setReplyToError(ERR_INVALID_REQ, HTTP_EXPECTATION_FAILED, request->method, http->uri,
+ conn->clientConnection->remote, request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
+ conn->flags.readMore = false;
goto finish;
}
}
assert (repContext);
repContext->setReplyToError(ERR_TOO_BIG,
HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL,
- conn->peer, http->request, NULL, NULL);
+ conn->clientConnection->remote, http->request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
+ conn->flags.readMore = false;
goto finish;
}
* 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;
}
}
* Attempt to parse one or more requests from the input buffer.
* If a request is successfully parsed, even if the next request
* is only partially parsed, it will return TRUE.
- * do_next_read is updated to indicate whether a read should be
- * scheduled.
*/
- static bool
- clientParseRequest(ConnStateData * conn, bool &do_next_read)
+ bool
+ ConnStateData::clientParseRequests()
{
HttpRequestMethod method;
- ClientSocketContext *context;
bool parsed_req = false;
HttpVersion http_ver;
- HttpParser hp;
- debugs(33, 5, HERE << conn->clientConnection << ": attempting to parse");
- debugs(33, 5, HERE << "FD " << fd << ": attempting to parse");
++ debugs(33, 5, HERE << clientConnection << ": attempting to parse");
// Loop while we have read bytes that are not needed for producing the body
- // On errors, bodyPipe may become nil, but readMoreRequests will be cleared
- while (conn->in.notYetUsed > 0 && !conn->bodyPipe &&
- conn->flags.readMoreRequests) {
- connStripBufferWhitespace (conn);
+ // On errors, bodyPipe may become nil, but readMore will be cleared
+ while (in.notYetUsed > 0 && !bodyPipe && flags.readMore) {
+ connStripBufferWhitespace(this);
/* Don't try to parse if the buffer is empty */
-
- if (conn->in.notYetUsed == 0)
+ if (in.notYetUsed == 0)
break;
/* Limit the number of concurrent requests to 2 */
/* status -1 or 1 */
if (context) {
- debugs(33, 5, HERE << conn->clientConnection << ": parsed a request");
- debugs(33, 5, HERE << "FD " << fd << ": parsed a request");
- commSetTimeout(fd, Config.Timeout.lifetime, clientLifetimeTimeout,
- context->http);
++ debugs(33, 5, HERE << clientConnection << ": parsed a request");
+ AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "clientLifetimeTimeout",
+ CommTimeoutCbPtrFun(clientLifetimeTimeout, context->http));
- commSetConnTimeout(conn->clientConnection, Config.Timeout.lifetime, timeoutCall);
++ commSetConnTimeout(clientConnection, Config.Timeout.lifetime, timeoutCall);
- clientProcessRequest(conn, &hp, context, method, http_ver);
+ clientProcessRequest(this, &parser_, context, method, http_ver);
- parsed_req = true;
+ parsed_req = true; // XXX: do we really need to parse everything right NOW ?
if (context->mayUseConnection()) {
- debugs(33, 3, "clientParseRequest: Not reading, as this request may need the connection");
- do_next_read = 0;
+ debugs(33, 3, HERE << "Not parsing new requests, as this request may need the connection");
break;
}
}
void
ConnStateData::clientReadRequest(const CommIoCbParams &io)
{
- debugs(33,5,HERE << "clientReadRequest FD " << io.fd << " size " << io.size);
+ debugs(33,5,HERE << io.conn << " size " << io.size);
Must(reading());
reader = NULL;
- bool do_next_read = 1; /* the default _is_ to read data! - adrian */
- assert (io.fd == fd);
-
/* Bail out quickly on COMM_ERR_CLOSING - close handlers will tidy up */
if (io.flag == COMM_ERR_CLOSING) {
}
/* It might be half-closed, we can't tell */
- fd_table[fd].flags.socket_eof = 1;
+ fd_table[io.conn->fd].flags.socket_eof = 1;
- commMarkHalfClosed(fd);
+ commMarkHalfClosed(io.conn->fd);
- do_next_read = 0;
-
- fd_note(fd, "half-closed");
+ fd_note(io.conn->fd, "half-closed");
/* There is one more close check at the end, to detect aborted
* (partial) requests. At this point we can't tell if the request
/* Process next request */
if (getConcurrentRequestCount() == 0)
- fd_note(fd, "Reading next request");
+ fd_note(io.fd, "Reading next request");
- if (! clientParseRequest(this, do_next_read)) {
+ if (!clientParseRequests()) {
if (!isOpen())
return;
/*
}
#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
debugs(33, 1, "Notice: httpd_accel_no_pmtu_disc not supported on your platform");
reported = 1;
}
+#endif
+ }
+
+ typedef CommCbMemFunT<ConnStateData, CommCloseCbParams> Dialer;
+ AsyncCall::Pointer call = JobCallback(33, 5, Dialer, result, ConnStateData::connStateClosed);
+ comm_add_close_handler(client->fd, call);
+
+ if (Config.onoff.log_fqdn)
+ fqdncache_gethostbyaddr(client->remote, FQDN_LOOKUP_IF_MISS);
+#if USE_IDENT
+ if (Ident::TheConfig.identLookup) {
+ ACLFilledChecklist identChecklist(Ident::TheConfig.identLookup, NULL, NULL);
+ identChecklist.src_addr = client->remote;
+ identChecklist.my_addr = client->local;
+ if (identChecklist.fastCheck())
+ Ident::Start(client, clientIdentDone, result);
+ }
#endif
+#if USE_SQUID_EUI
+ if (Eui::TheConfig.euiLookup) {
+ if (client->remote.IsIPv4()) {
+ result->clientConnection->remoteEui48.lookup(client->remote);
+ } else if (client->remote.IsIPv6()) {
+ result->clientConnection->remoteEui64.lookup(client->remote);
+ }
}
+#endif
+
+ clientdbEstablished(client->remote, 1);
- result->flags.readMoreRequests = true;
+ result->flags.readMore = true;
return result;
}
connState->readSomeData();
- clientdbEstablished(details->peer, 1);
-
#if USE_DELAY_POOLS
-- fd_table[newfd].clientInfo = NULL;
++ fd_table[details->fd].clientInfo = NULL;
if (Config.onoff.client_db) {
/* it was said several times that client write limiter does not work if client_db is disabled */
// TODO: we check early to limit error response bandwith but we
// should recheck when we can honor delay_pool_uses_indirect
-- ch.src_addr = details->peer;
-- ch.my_addr = details->me;
++ ch.src_addr = details->remote;
++ ch.my_addr = details->local;
if (ch.fastCheck()) {
/* request client information from db after we did all checks
this will save hash lookup if client failed checks */
-- ClientInfo * cli = clientdbGetInfo(details->peer);
++ ClientInfo * cli = clientdbGetInfo(details->remote);
assert(cli);
/* put client info in FDE */
-- fd_table[newfd].clientInfo = cli;
++ fd_table[details->fd].clientInfo = cli;
/* setup write limiter for this request */
const double burst = floor(0.5 +
assert(areAllContextsForThisConnection());
freeAllContexts();
//currentobject->connIsFinished();
- debugs(33, 5, HERE << "converting FD " << fd << " to SSL");
+
+ // We are going to read new request
+ flags.readMore = true;
+ debugs(33, 5, HERE << "converting " << clientConnection << " to SSL");
return getSslContextStart();
}
}
#endif
- debugs(1, 1, "Accepting" <<
- (s->intercepted ? " intercepted" : "") <<
- (s->spoof_client_ip ? " spoofing" : "") <<
- (s->sslBump ? " bumpy" : "") <<
- (s->accel ? " accelerated" : "")
+/// process clientHttpConnectionsOpen result
+static void
+clientListenerConnectionOpened(http_port_list *s, const Ipc::FdNoteId portTypeNote, const Subscription::Pointer &sub)
+{
+ if (!OpenedHttpSocket(s->listenConn, portTypeNote))
+ return;
+
+ Must(s);
+ Must(Comm::IsConnOpen(s->listenConn));
+
+ // TCP: setup a job to handle accept() with subscribed handler
+ AsyncJob::Start(new Comm::TcpAcceptor(s->listenConn, FdNote(portTypeNote), sub));
+
++ debugs(1, 1, "Accepting " <<
++ (s->intercepted ? "NAT intercepted " : "") <<
++ (s->spoof_client_ip ? "TPROXY spoofing " : "") <<
++ (s->sslBump ? "SSL bumped " : "") <<
++ (s->accel ? "reverse-proxy " : "")
+ << FdNote(portTypeNote) << " connections at "
+ << s->listenConn);
+
+ Must(AddOpenedHttpSocket(s->listenConn)); // otherwise, we have received a fd we did not ask for
+}
+
void
clientOpenListenSockets(void)
{
}
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
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 */
}
void writeControlMsg(HttpControlMsg &msg);
protected:
- static IOCB WroteControlMsg; //(int fd, char *bufnotused, size_t size, comm_err_t errflag, int xerrno, void *data);
- static void WroteControlMsg(int fd, char *bufnotused, size_t size, comm_err_t errflag, int xerrno, void *data);
- void wroteControlMsg(int fd, char *bufnotused, size_t size, comm_err_t errflag, int xerrno);
++ static IOCB WroteControlMsg;
+ void wroteControlMsg(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag, int xerrno);
private:
CBDATA_CLASS(ClientSocketContext);
};
- /**
- * Manages a connection to a client.
- *
- * Multiple requests (up to 2) can be pipelined. This object is responsible for managing
- * which one is currently being fulfilled and what happens to the queue if the current one
- * causes the client connection to be closed early.
- *
- * Act as a manager for the connection and passes data in buffer to the current parser.
- * the parser has ambiguous scope at present due to being made from global functions
- * I believe this object uses the parser to identify boundaries and kick off the
- * actual HTTP request handling objects (ClientSocketContext, ClientHttpRequest, HttpRequest)
- *
- * If the above can be confirmed accurate we can call this object PipelineManager or similar
- */
-class ConnectionDetail;
-
+ /** A connection to a socket */
class ConnStateData : public BodyProducer, public HttpControlMsgSink
{
*/
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 {
private:
int connReadWasError(comm_err_t flag, int size, int xerrno);
int connFinishedWithConn(int size);
- void clientMaybeReadData(int do_next_read);
- void clientAfterReadingRequests(int do_next_read);
+ void clientAfterReadingRequests();
private:
- CBDATA_CLASS2(ConnStateData);
- // XXX: CBDATA macro plays with public/private exposing all of the supposedly below private fields...
+ HttpParser parser_;
- bool transparent_;
+ // XXX: CBDATA plays with public/private and leaves the following 'private' fields all public... :(
+ CBDATA_CLASS2(ConnStateData);
bool closing_;
bool switchedToHttps_;
* 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");
/** 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);
}
}
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;
_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;
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;
return -1;
}
- // temporary for the transition. comm_openex will eventually have a conn to play with.
- debugs(50, 3, "comm_openex: Opened socket FD " << new_socket << " : family=" << AI->ai_family << ", type=" << AI->ai_socktype << ", protocol=" << AI->ai_protocol );
++ // XXX: temporary for the transition. comm_openex will eventually have a conn to play with.
+ Comm::ConnectionPointer conn = new Comm::Connection;
+ conn->local = addr;
+ conn->fd = new_socket;
+
+ debugs(50, 3, "comm_openex: Opened socket " << conn << " : family=" << AI->ai_family << ", type=" << AI->ai_socktype << ", protocol=" << AI->ai_protocol );
/* set TOS if needed */
if (tos)
PROF_stop(comm_open);
- // XXX transition only. prevent conn from closing the new FD on functio exit.
++ // XXX transition only. prevent conn from closing the new FD on function exit.
+ conn->fd = -1;
return new_socket;
}
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;
}
*/
}
- #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<Params>(callback);
- params.fd = fd;
- params.dns = dns;
- params.flag = status;
- params.xerrno = xerrno;
- ScheduleCallHere(callback);
- callback = NULL;
-
- commConnectFree(fd, this);
-}
-
-static void
-commConnectFree(int fd, void *data)
-{
- ConnectStateData *cs = (ConnectStateData *)data;
- debugs(5, 3, "commConnectFree: FD " << fd);
-// delete cs->callback;
- cs->callback = NULL;
- safe_free(cs->host);
- delete cs;
-}
-
-static void
-copyFDFlags(int to, fde *F)
-{
- if (F->flags.close_on_exec)
- commSetCloseOnExec(to);
-
- if (F->flags.nonblocking)
- commSetNonBlocking(to);
-
-#ifdef TCP_NODELAY
-
- if (F->flags.nodelay)
- commSetTcpNoDelay(to);
-
-#endif
-
- if (Config.tcpRcvBufsz > 0)
- commSetTcpRcvbuf(to, Config.tcpRcvBufsz);
-}
-
-/* Reset FD so that we can connect() again */
--int
- commSetTimeout_old(int fd, int timeout, CTCB * handler, void *data)
-ConnectStateData::commResetFD()
--{
- debugs(5, 3, HERE << "FD " << fd << " timeout " << timeout);
- assert(fd >= 0);
- assert(fd < Squid_MaxFD);
-
-// XXX: do we have to check this?
-//
-// if (!cbdataReferenceValid(callback.data))
-// return 0;
-
- statCounter.syscalls.sock.sockets++;
-
-- fde *F = &fd_table[fd];
- assert(F->flags.open);
--
- if (timeout < 0) {
- cbdataReferenceDone(F->timeout_data);
- F->timeout_handler = NULL;
- F->timeout = 0;
- } else {
- if (handler) {
- cbdataReferenceDone(F->timeout_data);
- F->timeout_handler = handler;
- F->timeout_data = cbdataReference(data);
- }
- struct addrinfo *AI = NULL;
- F->local_addr.GetAddrInfo(AI);
- int new_family = AI->ai_family;
--
- F->timeout = squid_curtime + (time_t) timeout;
- int fd2 = socket(new_family, AI->ai_socktype, AI->ai_protocol);
-
- if (fd2 < 0) {
- debugs(5, DBG_CRITICAL, HERE << "WARNING: FD " << fd2 << " socket failed to allocate: " << xstrerror());
-
- if (ENFILE == errno || EMFILE == errno)
- fdAdjustReserved();
-
- F->local_addr.FreeAddrInfo(AI);
- return 0;
-- }
--
- return F->timeout;
- }
-#ifdef _SQUID_MSWIN_
-
- /* On Windows dup2() can't work correctly on Sockets, the */
- /* workaround is to close the destination Socket before call them. */
- close(fd);
-
--#endif
-
- if (dup2(fd2, fd) < 0) {
- debugs(5, DBG_CRITICAL, HERE << "WARNING: dup2(FD " << fd2 << ", FD " << fd << ") failed: " << xstrerror());
-
- if (ENFILE == errno || EMFILE == errno)
- fdAdjustReserved();
-
- close(fd2);
-
- F->local_addr.FreeAddrInfo(AI);
- return 0;
- }
- Comm::ResetSelect(fd);
-
- close(fd2);
-
- debugs(50, 3, "commResetFD: Reset socket FD " << fd << "->" << fd2 << " : family=" << new_family );
-
- /* INET6: copy the new sockets family type to the FDE table */
- F->sock_family = new_family;
-
- F->flags.called_connect = 0;
-
- /*
- * yuck, this has assumptions about comm_open() arguments for
- * the original socket
- */
-
- /* MUST be done before binding or face OS Error: "(99) Cannot assign requested address"... */
- if ( F->flags.transparent ) {
- comm_set_transparent(fd);
- }
-
- if (commBind(fd, *AI) != COMM_OK) {
- debugs(5, DBG_CRITICAL, "WARNING: Reset of FD " << fd << " for " << F->local_addr << " failed to bind: " << xstrerror());
- F->local_addr.FreeAddrInfo(AI);
- return 0;
- }
- F->local_addr.FreeAddrInfo(AI);
-
- if (F->tosToServer)
- Ip::Qos::setSockTos(fd, F->tosToServer);
-
- if (F->nfmarkToServer)
- Ip::Qos::setSockNfmark(fd, F->nfmarkToServer);
-
- if ( Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && F->local_addr.IsIPv6() )
- comm_set_v6only(fd, 1);
-
- copyFDFlags(fd, F);
-
- return 1;
-}
--
+// Legacy pre-AsyncCalls API for FD timeouts.
int
-ConnectStateData::commRetryConnect()
+commSetTimeout(int fd, int timeout, CTCB * handler, void *data)
{
- assert(addrcount > 0);
-
- if (addrcount == 1) {
- if (tries >= Config.retry.maxtries)
- return 0;
-
- if (squid_curtime - connstart > Config.Timeout.connect)
- return 0;
- } else {
- if (tries > addrcount) {
- /* Flush bad address count in case we are
- * skipping over incompatible protocol
- */
- ipcacheMarkAllGood(host);
- return 0;
- }
- }
-
- return commResetFD();
-}
-
-static void
-commReconnect(void *data)
-{
- ConnectStateData *cs = (ConnectStateData *)data;
- ipcache_nbgethostbyname(cs->host, commConnectDnsHandle, cs);
-}
-
-/** Connect SOCK to specified DEST_PORT at DEST_HOST. */
-void
-ConnectStateData::Connect(int fd, void *me)
-{
- ConnectStateData *cs = (ConnectStateData *)me;
- assert (cs->fd == fd);
- cs->connect();
-}
-
-void
-ConnectStateData::defaults()
-{
- S = default_addr;
- S.SetPort(default_port);
+ AsyncCall::Pointer call;
+ debugs(5, 3, HERE << "FD " << fd << " timeout " << timeout);
+ if (handler != NULL)
+ call=commCbCall(5,4, "SomeTimeoutHandler", CommTimeoutCbPtrFun(handler, data));
+ else
+ call = NULL;
+ return commSetTimeout(fd, timeout, call);
}
-void
-ConnectStateData::connect()
-{
- defaults();
-
- debugs(5,5, HERE << "to " << S);
-
- switch (comm_connect_addr(fd, S) ) {
-
- case COMM_INPROGRESS:
- debugs(5, 5, HERE << "FD " << fd << ": COMM_INPROGRESS");
- Comm::SetSelect(fd, COMM_SELECT_WRITE, ConnectStateData::Connect, this, 0);
- break;
-
- case COMM_OK:
- debugs(5, 5, HERE << "FD " << fd << ": COMM_OK - connected");
- ipcacheMarkGoodAddr(host, S);
- callCallback(COMM_OK, 0);
- break;
-
- case COMM_ERR_PROTOCOL:
- debugs(5, 5, HERE "FD " << fd << ": COMM_ERR_PROTOCOL - try again");
- /* problem using the desired protocol over this socket.
- * skip to the next address and hope it's more compatible
- * but do not mark the current address as bad
- */
- tries++;
- if (commRetryConnect()) {
- /* Force an addr cycle to move forward to the next possible address */
- ipcacheCycleAddr(host, NULL);
- eventAdd("commReconnect", commReconnect, this, this->addrcount == 1 ? 0.05 : 0.0, 0);
- } else {
- debugs(5, 5, HERE << "FD " << fd << ": COMM_ERR_PROTOCOL - ERR tried too many times already.");
- callCallback(COMM_ERR_CONNECT, errno);
- }
- break;
-
- default:
- debugs(5, 5, HERE "FD " << fd << ": * - try again");
- tries++;
- ipcacheMarkBadAddr(host, S);
-
-#if USE_ICMP
- if (Config.onoff.test_reachability)
- netdbDeleteAddrNetwork(S);
-#endif
-
- if (commRetryConnect()) {
- eventAdd("commReconnect", commReconnect, this, this->addrcount == 1 ? 0.05 : 0.0, 0);
- } else {
- debugs(5, 5, HERE << "FD " << fd << ": * - ERR tried too many times already.");
- callCallback(COMM_ERR_CONNECT, errno);
- }
- }
-}
-/*
+// Legacy pre-Comm::Connection API for FD timeouts
+// still used by non-socket FD code dealing with pipes and IPC sockets.
int
-commSetTimeout_old(int fd, int timeout, PF * handler, void *data)
+commSetTimeout(int fd, int timeout, AsyncCall::Pointer &callback)
{
debugs(5, 3, HERE << "FD " << fd << " timeout " << timeout);
assert(fd >= 0);
* closed, TCP generates a RESET
*/
void
-comm_reset_close(int fd)
+comm_reset_close(Comm::ConnectionPointer &conn)
{
- debugs(50, DBG_CRITICAL, "ERROR: Closing FD " << conn->fd << " with TCP RST: " << xstrerror());
+ struct linger L;
+ L.l_onoff = 1;
+ L.l_linger = 0;
+
+ if (setsockopt(conn->fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0)
++ debugs(50, DBG_CRITICAL, "ERROR: Closing " << conn << " with TCP RST: " << xstrerror());
+
+ conn->close();
+}
+// Legacy close function.
+void
+old_comm_reset_close(int fd)
+{
struct linger L;
L.l_onoff = 1;
L.l_linger = 0;
--- /dev/null
- //#include "base/TextException.h"
+/*
+ * DEBUG: section 05 Socket Connection Opener
+ */
+
+#include "config.h"
+#include "comm/ConnOpener.h"
+#include "comm/Connection.h"
+#include "comm/Loops.h"
+#include "comm.h"
+#include "fde.h"
+#include "icmp/net_db.h"
+#include "SquidTime.h"
+
+namespace Comm {
+ CBDATA_CLASS_INIT(ConnOpener);
+};
+
+Comm::ConnOpener::ConnOpener(Comm::ConnectionPointer &c, AsyncCall::Pointer &handler, time_t ctimeout) :
+ AsyncJob("Comm::ConnOpener"),
+ host_(NULL),
+ conn_(c),
+ callback_(handler),
+ totalTries_(0),
+ failRetries_(0),
+ connectTimeout_(ctimeout),
+ connectStart_(0)
+{}
+
+Comm::ConnOpener::~ConnOpener()
+{
+ safe_free(host_);
+}
+
+bool
+Comm::ConnOpener::doneAll() const
+{
+ // is the conn_ to be opened still waiting?
+ if (conn_ == NULL) {
+ return AsyncJob::doneAll();
+ }
+
+ // is the callback still to be called?
+ if (callback_ == NULL || callback_->canceled()) {
+ return AsyncJob::doneAll();
+ }
+
+ return false;
+}
+
+void
+Comm::ConnOpener::swanSong()
+{
+ // cancel any event watchers
+ // done here to get the "swanSong" mention in cancel debugging.
+ if (calls_.earlyAbort_ != NULL) {
+ calls_.earlyAbort_->cancel("Comm::ConnOpener::swanSong");
+ calls_.earlyAbort_ = NULL;
+ }
+ if (calls_.timeout_ != NULL) {
+ calls_.timeout_->cancel("Comm::ConnOpener::swanSong");
+ calls_.timeout_ = NULL;
+ }
+
+ // rollback what we can from the job state
+ if (conn_ != NULL && conn_->isOpen()) {
+ // drop any handlers now to save a lot of cycles later
+ Comm::SetSelect(conn_->fd, COMM_SELECT_WRITE, NULL, NULL, 0);
+ commUnsetConnTimeout(conn_);
+ // it never reached fully open, so abort the FD
+ conn_->close();
+ }
+
+ if (callback_ != NULL) {
+ if (callback_->canceled())
+ callback_ = NULL;
+ else
+ // inform the still-waiting caller we are dying
+ doneConnecting(COMM_ERR_CONNECT, 0);
+ }
+
+ AsyncJob::swanSong();
+}
+
+void
+Comm::ConnOpener::setHost(const char * new_host)
+{
+ // unset and erase if already set.
+ if (host_ != NULL)
+ safe_free(host_);
+
+ // set the new one if given.
+ if (new_host != NULL)
+ host_ = xstrdup(new_host);
+}
+
+const char *
+Comm::ConnOpener::getHost() const
+{
+ return host_;
+}
+
+/**
+ * Connection attempt are completed. One way or the other.
+ * Pass the results back to the external handler.
+ * NP: on connection errors the connection close() must be called first.
+ */
+void
+Comm::ConnOpener::doneConnecting(comm_err_t status, int xerrno)
+{
+ // only mark the address good/bad AFTER connect is finished.
+ if (host_ != NULL) {
+ if (xerrno == 0)
+ ipcacheMarkGoodAddr(host_, conn_->remote);
+ else {
+ ipcacheMarkBadAddr(host_, conn_->remote);
+#if USE_ICMP
+ if (Config.onoff.test_reachability)
+ netdbDeleteAddrNetwork(conn_->remote);
+#endif
+ }
+ }
+
+ if (callback_ != NULL) {
+ typedef CommConnectCbParams Params;
+ Params ¶ms = GetCommParams<Params>(callback_);
+ params.conn = conn_;
+ params.flag = status;
+ params.xerrno = xerrno;
+ ScheduleCallHere(callback_);
+ callback_ = NULL;
+ }
+
+ /* ensure cleared local state, we are done. */
+ conn_ = NULL;
+}
+
+void
+Comm::ConnOpener::start()
+{
+ Must(conn_ != NULL);
+
+ /* get a socket open ready for connecting with */
+ if (!conn_->isOpen()) {
+#if USE_IPV6
+ /* outbound sockets have no need to be protocol agnostic. */
+ if (conn_->remote.IsIPv4()) {
+ conn_->local.SetIPv4();
+ }
+#endif
+ conn_->fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, conn_->local, conn_->flags, conn_->tos, conn_->nfmark, host_);
+ if (!conn_->isOpen()) {
+ doneConnecting(COMM_ERR_CONNECT, 0);
+ return;
+ }
+ }
+
+ typedef CommCbMemFunT<Comm::ConnOpener, CommConnectCbParams> abortDialer;
+ calls_.earlyAbort_ = JobCallback(5, 4, abortDialer, this, Comm::ConnOpener::earlyAbort);
+ comm_add_close_handler(conn_->fd, calls_.earlyAbort_);
+
+ typedef CommCbMemFunT<Comm::ConnOpener, CommTimeoutCbParams> timeoutDialer;
+ calls_.timeout_ = JobCallback(5, 4, timeoutDialer, this, Comm::ConnOpener::timeout);
+ debugs(5, 3, HERE << conn_ << " timeout " << connectTimeout_);
+ commSetConnTimeout(conn_, connectTimeout_, calls_.timeout_);
+
+ connectStart_ = squid_curtime;
+ connect();
+}
+
+void
+Comm::ConnOpener::connected()
+{
+ /*
+ * stats.conn_open is used to account for the number of
+ * connections that we have open to the peer, so we can limit
+ * based on the max-conn option. We need to increment here,
+ * even if the connection may fail.
+ */
+ if (conn_->getPeer())
+ conn_->getPeer()->stats.conn_open++;
+
+ lookupLocalAddress();
+
+ /* TODO: remove these fd_table accesses. But old code still depends on fd_table flags to
+ * indicate the state of a raw fd object being passed around.
+ * Also, legacy code still depends on comm_local_port() with no access to Comm::Connection
+ * when those are done comm_local_port can become one of our member functions to do the below.
+ */
+ fd_table[conn_->fd].flags.open = 1;
+ fd_table[conn_->fd].local_addr = conn_->local;
+}
+
+/** Make an FD connection attempt.
+ * Handles the case(s) when a partially setup connection gets closed early.
+ */
+void
+Comm::ConnOpener::connect()
+{
+ Must(conn_ != NULL);
+
+ // our parent Jobs signal abort by cancelling their callbacks.
+ if (callback_ == NULL || callback_->canceled())
+ return;
+
+ totalTries_++;
+
+ switch (comm_connect_addr(conn_->fd, conn_->remote) ) {
+
+ case COMM_INPROGRESS:
+ // check for timeout FIRST.
+ if (squid_curtime - connectStart_ > connectTimeout_) {
+ debugs(5, 5, HERE << conn_ << ": * - ERR took too long already.");
+ calls_.earlyAbort_->cancel("Comm::ConnOpener::connect timed out");
+ calls_.earlyAbort_ = NULL;
+ conn_->close();
+ doneConnecting(COMM_TIMEOUT, errno);
+ return;
+ } else {
+ debugs(5, 5, HERE << conn_ << ": COMM_INPROGRESS");
+ Comm::SetSelect(conn_->fd, COMM_SELECT_WRITE, Comm::ConnOpener::InProgressConnectRetry, this, 0);
+ }
+ break;
+
+ case COMM_OK:
+ debugs(5, 5, HERE << conn_ << ": COMM_OK - connected");
+ connected();
+ doneConnecting(COMM_OK, 0);
+ break;
+
+ default:
+ failRetries_++;
+
+ // check for timeout FIRST.
+ if(squid_curtime - connectStart_ > connectTimeout_) {
+ debugs(5, 5, HERE << conn_ << ": * - ERR took too long to receive response.");
+ calls_.earlyAbort_->cancel("Comm::ConnOpener::connect timed out");
+ calls_.earlyAbort_ = NULL;
+ conn_->close();
+ doneConnecting(COMM_TIMEOUT, errno);
+ } else if (failRetries_ < Config.connect_retries) {
+ debugs(5, 5, HERE << conn_ << ": * - try again");
+ eventAdd("Comm::ConnOpener::DelayedConnectRetry", Comm::ConnOpener::DelayedConnectRetry, this, 0.05, 0);
+ return;
+ } else {
+ // send ERROR back to the upper layer.
+ debugs(5, 5, HERE << conn_ << ": * - ERR tried too many times already.");
+ calls_.earlyAbort_->cancel("Comm::ConnOpener::connect failed");
+ calls_.earlyAbort_ = NULL;
+ conn_->close();
+ doneConnecting(COMM_ERR_CONNECT, errno);
+ }
+ }
+}
+
+/**
+ * Lookup local-end address and port of the TCP link just opened.
+ * This ensure the connection local details are set correctly
+ */
+void
+Comm::ConnOpener::lookupLocalAddress()
+{
+ struct addrinfo *addr = NULL;
+ conn_->local.InitAddrInfo(addr);
+
+ if (getsockname(conn_->fd, addr->ai_addr, &(addr->ai_addrlen)) != 0) {
+ debugs(50, DBG_IMPORTANT, "ERROR: Failed to retrieve TCP/UDP details for socket: " << conn_ << ": " << xstrerror());
+ conn_->local.FreeAddrInfo(addr);
+ return;
+ }
+
+ conn_->local = *addr;
+ conn_->local.FreeAddrInfo(addr);
+ debugs(5, 6, HERE << conn_);
+}
+
+/** Abort connection attempt.
+ * Handles the case(s) when a partially setup connection gets closed early.
+ */
+void
+Comm::ConnOpener::earlyAbort(const CommConnectCbParams &io)
+{
+ debugs(5, 3, HERE << io.conn);
+ doneConnecting(COMM_ERR_CLOSING, io.xerrno); // NP: is closing or shutdown better?
+}
+
+/**
+ * Handles the case(s) when a partially setup connection gets timed out.
+ * NP: When commSetConnTimeout accepts generic CommCommonCbParams this can die.
+ */
+void
+Comm::ConnOpener::timeout(const CommTimeoutCbParams &)
+{
+ connect();
+}
+
+/* Legacy Wrapper for the retry event after COMM_INPROGRESS
+ * XXX: As soon as Comm::SetSelect() accepts Async calls we can use a ConnOpener::connect call
+ */
+void
+Comm::ConnOpener::InProgressConnectRetry(int fd, void *data)
+{
+ ConnOpener *cs = static_cast<Comm::ConnOpener *>(data);
+ assert(cs);
+
+ // Ew. we are now outside the all AsyncJob protections.
+ // get back inside by scheduling another call...
+ typedef NullaryMemFunT<Comm::ConnOpener> Dialer;
+ AsyncCall::Pointer call = JobCallback(5, 4, Dialer, cs, Comm::ConnOpener::connect);
+ ScheduleCallHere(call);
+}
+
+/* Legacy Wrapper for the retry event with small delay after errors.
+ * XXX: As soon as eventAdd() accepts Async calls we can use a ConnOpener::connect call
+ */
+void
+Comm::ConnOpener::DelayedConnectRetry(void *data)
+{
+ ConnOpener *cs = static_cast<Comm::ConnOpener *>(data);
+ assert(cs);
+
+ // Ew. we are now outside the all AsyncJob protections.
+ // get back inside by scheduling another call...
+ typedef NullaryMemFunT<Comm::ConnOpener> Dialer;
+ AsyncCall::Pointer call = JobCallback(5, 4, Dialer, cs, Comm::ConnOpener::connect);
+ ScheduleCallHere(call);
+}
iocb_table = static_cast<CbEntry*>(xcalloc(Squid_MaxFD, sizeof(CbEntry)));
for (int pos = 0; pos < Squid_MaxFD; pos++) {
iocb_table[pos].fd = pos;
- // iocb_table[pos].readcb.fd = pos;
- iocb_table[pos].readcb.fd = pos;
iocb_table[pos].readcb.type = IOCB_READ;
- // iocb_table[pos].writecb.fd = pos;
- iocb_table[pos].writecb.fd = pos;
iocb_table[pos].writecb.type = IOCB_WRITE;
}
}
Write.h \
\
comm_internal.h
++
++EXTRA_DIST= stub_libcomm.cc
#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"
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;
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;
#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"
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;
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;
--- /dev/null
--- /dev/null
++#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
#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)
#include "DelayUser.h"
#include "DelayTagged.h"
#include "ip/Address.h"
++#include "comm/Connection.h"
/// \ingroup DelayPoolsInternal
long DelayPools::MemoryUsed = 0;
*/
#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"
#endif
static void idnsCacheQuery(idns_query * q);
static void idnsSendQuery(idns_query * q);
+ static IOCB idnsReadVCHeader;
static void idnsDoSendQueryVC(nsvc *vc);
- static IOCB idnsReadVCHeader;
+static CNCB idnsInitVCConnected;
+static IOCB idnsReadVC;
+static IOCB idnsSentQueryVC;
static int idnsFromKnownNameserver(Ip::Address const &from);
static idns_query *idnsFindQuery(unsigned short id);
vc->busy = 1;
- commSetConnTimeout(vc->conn, Config.Timeout.idns_query, nil);
+ // Comm needs seconds but idnsCheckQueue() will check the exact timeout
+ const int timeout = (Config.Timeout.idns_query % 1000 ?
+ Config.Timeout.idns_query + 1000 : Config.Timeout.idns_query) / 1000;
+ AsyncCall::Pointer nil;
- commSetTimeout(vc->fd, timeout, NULL, NULL);
+
++ commSetConnTimeout(vc->conn, timeout, nil);
AsyncCall::Pointer call = commCbCall(78, 5, "idnsSentQueryVC",
CommIoCbPtrFun(&idnsSentQueryVC, vc));
*
*/
#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"
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;
}
#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"
* 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
#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"
/* 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();
// 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);
#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"
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;
fwd->serverClosed(fd);
}
- #if 0
--static void
--fwdConnectStartWrapper(void *data)
--{
-- FwdState *fwd = (FwdState *) data;
-- fwd->connectStart();
--}
- #endif
--
#if USE_SSL
static void
fwdNegotiateSSLWrapper(int fd, void *data)
FwdState *fwd = (FwdState *) data;
fwd->negotiateSSL(fd);
}
+
#endif
-static void
-fwdConnectDoneWrapper(int server_fd, const DnsLookupDetails &dns, comm_err_t status, int xerrno, void *data)
-{
- FwdState *fwd = (FwdState *) data;
- fwd->connectDone(server_fd, dns, status, xerrno);
-}
-
-static void
-fwdConnectTimeoutWrapper(int fd, void *data)
+void
+fwdConnectDoneWrapper(const Comm::ConnectionPointer &conn, comm_err_t status, int xerrno, void *data)
{
FwdState *fwd = (FwdState *) data;
- fwd->connectTimeout(fd);
-}
-
-/*
- * Accounts for closed persistent connections
- */
-static void
-fwdPeerClosed(int fd, void *data)
-{
- peer *p = (peer *)data;
- p->stats.conn_open--;
+ fwd->connectDone(conn, status, xerrno);
}
/**** PRIVATE *****************************************************************/
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?
#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
if (ftimeout < ctimeout)
ctimeout = ftimeout;
- if (fs->_peer && request->flags.sslBumped == true) {
++ if (serverDestinations[0]->getPeer() && request->flags.sslBumped == true) {
+ debugs(50, 4, "fwdConnectStart: Ssl bumped connections through parrent proxy are not allowed");
+ ErrorState *anErr = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, request);
+ fail(anErr);
+ self = NULL; // refcounted
+ return;
+ }
+
request->flags.pinned = 0;
- if (fs->code == PINNED) {
+ if (serverDestinations[0]->peerType == PINNED) {
ConnStateData *pinned_connection = request->pinnedConnection();
assert(pinned_connection);
- fd = pinned_connection->validatePinnedConnection(request, fs->_peer);
- if (fd >= 0) {
+ serverConn = pinned_connection->validatePinnedConnection(request, serverDestinations[0]->getPeer());
+ if (Comm::IsConnOpen(serverConn)) {
- pinned_connection->unpinConnection(); // XXX: this should be just remove the pinning close handler ??
#if 0
- if (!fs->_peer)
- fs->code = HIER_DIRECT;
+ if (!serverConn->getPeer())
+ serverConn->peerType = HIER_DIRECT;
#endif
- server_fd = fd;
n_tries++;
request->flags.pinned = 1;
if (pinned_connection->pinnedAuth())
return;
}
/* Failure. Fall back on next path */
- debugs(17, 2, HERE << " Pinned connection " << pinned_connection << " not valid. Releasing.");
- request->releasePinnedConnection();
+ debugs(17,2,HERE << " Pinned connection " << pinned_connection << " not valid.");
- servers = fs->next;
- fwdServerFree(fs);
- connectStart();
+ serverDestinations.shift();
+ startConnectionOrFail();
return;
}
entry->mem_obj->checkUrlChecksum();
#endif
- outgoing = getOutgoingAddr(request, fs->_peer);
-
- // if IPv6 is disabled try to force IPv4-only outgoing.
- if (!Ip::EnableIpv6 && !outgoing.SetIPv4()) {
- debugs(50, 4, "fwdConnectStart: IPv6 is Disabled. Cannot connect from " << outgoing);
- ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
- anErr->xerrno = EAFNOSUPPORT;
- fail(anErr);
- self = NULL; // refcounted
- return;
- }
-
- // if IPv6 is split-stack, prefer IPv4
- if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK) {
- // NP: This is not a great choice of default,
- // but with the current Internet being IPv4-majority has a higher success rate.
- // if setting to IPv4 fails we dont care, that just means to use IPv6 outgoing.
- outgoing.SetIPv4();
+ /* Get the server side TOS and Netfilter mark to be set on the connection. */
+ if (Ip::Qos::TheConfig.isAclTosActive()) {
+ serverDestinations[0]->tos = GetTosToServer(request);
}
- #if SO_MARK
-
- tos_t tos = GetTosToServer(request);
-
+ #if SO_MARK && USE_LIBCAP
- nfmark_t mark = GetNfmarkToServer(request);
- debugs(17, 3, "fwdConnectStart: got outgoing addr " << outgoing << ", tos " << int(tos)
- << ", netfilter mark " << mark);
+ serverDestinations[0]->nfmark = GetNfmarkToServer(request);
+ debugs(17, 3, "fwdConnectStart: got outgoing addr " << serverDestinations[0]->local << ", tos " << int(serverDestinations[0]->tos)
+ << ", netfilter mark " << serverDestinations[0]->nfmark);
#else
- nfmark_t mark = 0;
- debugs(17, 3, "fwdConnectStart: got outgoing addr " << outgoing << ", tos " << int(tos));
+ serverDestinations[0]->nfmark = 0;
+ debugs(17, 3, "fwdConnectStart: got outgoing addr " << serverDestinations[0]->local << ", tos " << int(serverDestinations[0]->tos));
#endif
- int commFlags = COMM_NONBLOCKING;
- if (request->flags.spoof_client_ip) {
- if (!fs->_peer || !fs->_peer->options.no_tproxy)
- commFlags |= COMM_TRANSPARENT;
- // else no tproxy today ...
- }
-
- fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, outgoing, commFlags, tos, mark, url);
-
- debugs(17, 3, "fwdConnectStart: got TCP FD " << fd);
-
- if (fd < 0) {
- debugs(50, 4, "fwdConnectStart: " << xstrerror());
- ErrorState *anErr = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request);
- anErr->xerrno = errno;
- fail(anErr);
- self = NULL; // refcounted
- return;
- }
-
- server_fd = fd;
- n_tries++;
-
- if (!fs->_peer)
- origin_tries++;
-
- if (comm_local_port(fd))
- request->hier.peer_local_addr = fd_table[fd].local_addr;
-
- /*
- * stats.conn_open is used to account for the number of
- * connections that we have open to the peer, so we can limit
- * based on the max-conn option. We need to increment here,
- * even if the connection may fail.
- */
-
- if (fs->_peer) {
- fs->_peer->stats.conn_open++;
- comm_add_close_handler(fd, fwdPeerClosed, fs->_peer);
- }
-
- comm_add_close_handler(fd, fwdServerClosedWrapper, this);
-
- commSetTimeout(fd, ctimeout, fwdConnectTimeoutWrapper, this);
-
- updateHierarchyInfo();
- commConnectStart(fd, host, port, fwdConnectDoneWrapper, this);
-}
-
-void
-FwdState::startComplete(FwdServer * theServers)
-{
- debugs(17, 3, "fwdStartComplete: " << entry->url() );
-
- if (theServers != NULL) {
- servers = theServers;
- connectStart();
- } else {
- startFail();
- }
-}
-
-void
-FwdState::startFail()
-{
- debugs(17, 3, "fwdStartFail: " << entry->url() );
- ErrorState *anErr = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, request);
- anErr->xerrno = errno;
- fail(anErr);
- self = NULL; // refcounted
+ calls.connector = commCbCall(17,3, "fwdConnectDoneWrapper", CommConnectCbPtrFun(fwdConnectDoneWrapper, this));
+ Comm::ConnOpener *cs = new Comm::ConnOpener(serverDestinations[0], calls.connector, ctimeout);
+ cs->setHost(host);
+ AsyncJob::Start(cs);
}
void
{
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);
}
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)
{
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;
}
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;
}
kb_incr(&statCounter.server.all.kbytes_in, len);
kb_incr(&statCounter.server.other.kbytes_in, len);
+ }
- debugs(10, 5, "gopherReadReply: FD " << fd << " read len=" << len);
++ debugs(10, 5, HERE << conn << " read len=" << len);
+
+ if (flag == COMM_OK && len > 0) {
- commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
+ AsyncCall::Pointer nil;
+ commSetConnTimeout(conn, Config.Timeout.read, nil);
IOStats.Gopher.reads++;
for (clen = len - 1, bin = 0; clen; bin++)
debugs(50, 1, "gopherReadReply: error reading: " << xstrerror());
if (ignoreErrno(errno)) {
- do_next_read = 1;
- comm_read(fd, buf, read_sz, gopherReadReply, gopherState);
++ AsyncCall::Pointer call = commCbCall(5,4, "gopherReadReply",
++ CommIoCbPtrFun(gopherReadReply, gopherState));
++ comm_read(conn, buf, read_sz, call);
} else {
- ErrorState *err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, gopherState->fwd->request);
+ ErrorState *err;
+ err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, gopherState->fwd->request);
err->xerrno = errno;
gopherState->fwd->fail(err);
- comm_close(fd);
+ gopherState->serverConn->close();
- do_next_read = 0;
}
} else if (len == 0 && entry->isEmpty()) {
gopherState->fwd->fail(errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE, gopherState->fwd->request));
- comm_close(fd);
+ gopherState->serverConn->close();
- do_next_read = 0;
} else if (len == 0) {
/* Connection closed; retrieval done. */
/* flush the rest of data in temp buf if there is one. */
entry->timestampsSet();
entry->flush();
gopherState->fwd->complete();
- comm_close(fd);
+ gopherState->serverConn->close();
- do_next_read = 0;
} else {
if (gopherState->conversion != gopher_ds::NORMAL) {
gopherToHTML(gopherState, buf, len);
} else {
entry->append(buf, len);
}
-
- do_next_read = 1;
- }
-
- if (do_next_read) {
- comm_read(fd, buf, read_sz, gopherReadReply, gopherState);
+ AsyncCall::Pointer call = commCbCall(5,4, "gopherReadReply",
+ CommIoCbPtrFun(gopherReadReply, gopherState));
+ comm_read(conn, buf, read_sz, call);
}
- return;
}
/**
debugs(84, 5, "helperHandleRead: " << len << " bytes from " << hlp->id_name << " #" << srv->index + 1);
- if (flag != COMM_OK || len <= 0) {
- if (len < 0)
- debugs(84, 1, "helperHandleRead: FD " << conn->fd << " read: " << xstrerror());
-
+ if (flag != COMM_OK || len == 0) {
- comm_close(fd);
+ srv->closePipesSafely();
return;
}
srv->rbuf[0] = '\0';
}
- if (hlp->return_full_reply) {
- debugs(84, 3, HERE << "Return entire buffer");
- helperReturnBuffer(0, srv, hlp, srv->rbuf, srv->rbuf + srv->roffset);
- } else {
- while ((t = strchr(srv->rbuf, '\n'))) {
- /* end of reply found */
- char *msg = srv->rbuf;
- int i = 0;
- debugs(84, 3, "helperHandleRead: end of reply found");
-
- if (t > srv->rbuf && t[-1] == '\r')
- t[-1] = '\0';
+ while ((t = strchr(srv->rbuf, hlp->eom))) {
+ /* end of reply found */
+ char *msg = srv->rbuf;
+ int i = 0;
+ debugs(84, 3, "helperHandleRead: end of reply found");
- *t++ = '\0';
+ if (t > srv->rbuf && t[-1] == '\r' && hlp->eom == '\n')
+ t[-1] = '\0';
- if (hlp->childs.concurrency) {
- i = strtol(msg, &msg, 10);
+ *t++ = '\0';
- while (*msg && xisspace(*msg))
- msg++;
- }
+ if (hlp->childs.concurrency) {
+ i = strtol(msg, &msg, 10);
- helperReturnBuffer(i, srv, hlp, msg, t);
+ while (*msg && xisspace(*msg))
+ msg++;
}
+
+ helperReturnBuffer(i, srv, hlp, msg, t);
}
- if (srv->rfd != -1)
- comm_read(fd, srv->rbuf + srv->roffset, srv->rbuf_sz - srv->roffset - 1, helperHandleRead, srv);
+ if (Comm::IsConnOpen(srv->readPipe)) {
+ AsyncCall::Pointer call = commCbCall(5,4, "helperHandleRead",
+ CommIoCbPtrFun(helperHandleRead, srv));
+ comm_read(srv->readPipe, srv->rbuf + srv->roffset, srv->rbuf_sz - srv->roffset - 1, call);
+ }
}
static void
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;
}
#include "squid.h"
#include "cbdata.h"
- #include "HelperChildConfig.h"
+#include "comm/forward.h"
#include "ip/Address.h"
+ #include "HelperChildConfig.h"
class helper_request;
debugs(11,5,HERE << "HttpStateData " << this << " created");
ignoreCacheControl = false;
surrogateNoStore = false;
- fd = fwd->server_fd;
+ serverConnection = fwd->serverConnection();
readBuf = new MemBuf;
- readBuf->init();
+ readBuf->init(16*1024, 256*1024);
orig_request = HTTPMSGLOCK(fwd->request);
// reset peer response time stats for %<pt
int clen;
int len = io.size;
- // assert(serverConnection->fd == io.fd); // XXX: false when closing. serverConnection-> will already be -1.
- assert(fd == io.fd);
--
flags.do_next_read = 0;
- debugs(11, 5, "httpReadReply: FD " << fd << ": len " << len << ".");
+ debugs(11, 5, HERE << io.conn << ": len " << len << ".");
// Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us
if (io.flag == COMM_ERR_CLOSING) {
err->xerrno = io.xerrno;
fwd->fail(err);
flags.do_next_read = 0;
- comm_close(fd);
+ serverConnection->close();
}
+
return;
}
{
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);
}
*/
#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"
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);
/* 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 */
}
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
}
#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"
Mgr::Inquirer::HandleRemoteAck(response);
}
-int
+ #if SQUID_SNMP
+ void
+ Ipc::Coordinator::handleSnmpRequest(const Snmp::Request& request)
+ {
+ debugs(54, 4, HERE);
+
+ Snmp::Response response(request.requestId);
+ TypedMsgHdr message;
+ response.pack(message);
+ SendMessage(MakeAddr(strandAddrPfx, request.requestorId), message);
+
+ AsyncJob::Start(new Snmp::Inquirer(request, strands_));
+ }
+
+ void
+ Ipc::Coordinator::handleSnmpResponse(const Snmp::Response& response)
+ {
+ debugs(54, 4, HERE);
+ Snmp::Inquirer::HandleRemoteAck(response);
+ }
+ #endif
+
+Comm::ConnectionPointer
Ipc::Coordinator::openListenSocket(const SharedListenRequest& request,
int &errNo)
{
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
--- /dev/null
+ /*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+ #include "config.h"
+ #include "base/AsyncJobCalls.h"
+ #include "base/TextException.h"
++#include "errorpage.h"
++#include "HttpReply.h"
++#include "HttpRequest.h"
+ #include "ipc/Forwarder.h"
+ #include "ipc/Port.h"
+ #include "ipc/TypedMsgHdr.h"
+
+
+ CBDATA_NAMESPACED_CLASS_INIT(Ipc, Forwarder);
+
+ Ipc::Forwarder::RequestsMap Ipc::Forwarder::TheRequestsMap;
+ unsigned int Ipc::Forwarder::LastRequestId = 0;
+
+ Ipc::Forwarder::Forwarder(Request::Pointer aRequest, double aTimeout):
+ AsyncJob("Ipc::Forwarder"),
+ request(aRequest), timeout(aTimeout)
+ {
+ debugs(54, 5, HERE);
+ }
+
+ Ipc::Forwarder::~Forwarder()
+ {
+ debugs(54, 5, HERE);
+ Must(request->requestId == 0);
+ cleanup();
+ }
+
+ /// perform cleanup actions
+ void
+ Ipc::Forwarder::cleanup()
+ {
+ }
+
+ void
+ Ipc::Forwarder::start()
+ {
+ debugs(54, 3, HERE);
+
+ typedef NullaryMemFunT<Forwarder> Dialer;
+ AsyncCall::Pointer callback = JobCallback(54, 5, Dialer, this, Forwarder::handleRemoteAck);
+ if (++LastRequestId == 0) // don't use zero value as request->requestId
+ ++LastRequestId;
+ request->requestId = LastRequestId;
+ TheRequestsMap[request->requestId] = callback;
+ TypedMsgHdr message;
+
+ try {
+ request->pack(message);
+ } catch (...) {
+ // assume the pack() call failed because the message did not fit
+ // TODO: add a more specific exception?
+ handleError();
+ }
+
+ SendMessage(coordinatorAddr, message);
+ eventAdd("Ipc::Forwarder::requestTimedOut", &Forwarder::RequestTimedOut,
+ this, timeout, 0, false);
+ }
+
+ void
+ Ipc::Forwarder::swanSong()
+ {
+ debugs(54, 5, HERE);
+ removeTimeoutEvent();
+ if (request->requestId > 0) {
+ DequeueRequest(request->requestId);
+ request->requestId = 0;
+ }
+ cleanup();
+ }
+
+ bool
+ Ipc::Forwarder::doneAll() const
+ {
+ debugs(54, 5, HERE);
+ return request->requestId == 0;
+ }
+
+ /// called when Coordinator starts processing the request
+ void
+ Ipc::Forwarder::handleRemoteAck()
+ {
+ debugs(54, 3, HERE);
+ request->requestId = 0;
+ }
+
+ /// Ipc::Forwarder::requestTimedOut wrapper
+ void
+ Ipc::Forwarder::RequestTimedOut(void* param)
+ {
+ debugs(54, 3, HERE);
+ Must(param != NULL);
+ Forwarder* fwdr = static_cast<Forwarder*>(param);
+ // use async call to enable job call protection that time events lack
+ CallJobHere(54, 5, fwdr, Forwarder, requestTimedOut);
+ }
+
+ /// called when Coordinator fails to start processing the request [in time]
+ void
+ Ipc::Forwarder::requestTimedOut()
+ {
+ debugs(54, 3, HERE);
+ handleTimeout();
+ }
+
+ void
+ Ipc::Forwarder::handleError()
+ {
+ mustStop("error");
+ }
+
+ void
+ Ipc::Forwarder::handleTimeout()
+ {
+ mustStop("timeout");
+ }
+
+ /// terminate with an error
+ void
+ Ipc::Forwarder::handleException(const std::exception& e)
+ {
+ debugs(54, 3, HERE << e.what());
+ mustStop("exception");
+ }
+
+ void
+ Ipc::Forwarder::callException(const std::exception& e)
+ {
+ try {
+ handleException(e);
+ } catch (const std::exception& ex) {
+ debugs(54, DBG_CRITICAL, HERE << ex.what());
+ }
+ AsyncJob::callException(e);
+ }
+
+ /// returns and forgets the right Forwarder callback for the request
+ AsyncCall::Pointer
+ Ipc::Forwarder::DequeueRequest(unsigned int requestId)
+ {
+ debugs(54, 3, HERE);
+ Must(requestId != 0);
+ AsyncCall::Pointer call;
+ RequestsMap::iterator request = TheRequestsMap.find(requestId);
+ if (request != TheRequestsMap.end()) {
+ call = request->second;
+ Must(call != NULL);
+ TheRequestsMap.erase(request);
+ }
+ return call;
+ }
+
+ /// called when we are no longer waiting for Coordinator to respond
+ void
+ Ipc::Forwarder::removeTimeoutEvent()
+ {
+ if (eventFind(&Forwarder::RequestTimedOut, this))
+ eventDelete(&Forwarder::RequestTimedOut, this);
+ }
+
+ void
+ Ipc::Forwarder::HandleRemoteAck(unsigned int requestId)
+ {
+ debugs(54, 3, HERE);
+ Must(requestId != 0);
+
+ AsyncCall::Pointer call = DequeueRequest(requestId);
+ if (call != NULL)
+ ScheduleCallHere(call);
+ }
--- /dev/null
+ /*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+ #ifndef SQUID_IPC_FORWARDER_H
+ #define SQUID_IPC_FORWARDER_H
+
+ #include "base/AsyncJob.h"
++#include "mgr/ActionParams.h"
+ #include "ipc/Request.h"
+ #include <map>
+
+
+ namespace Ipc
+ {
+
+ /** Forwards a worker request to coordinator.
+ * Waits for an ACK from Coordinator
+ * Send the data unit with an error response if forwarding fails.
+ */
+ class Forwarder: public AsyncJob
+ {
+ public:
+ Forwarder(Request::Pointer aRequest, double aTimeout);
+ virtual ~Forwarder();
+
+ /// finds and calls the right Forwarder upon Coordinator's response
+ static void HandleRemoteAck(unsigned int requestId);
+
+ /* has-to-be-public AsyncJob API */
+ virtual void callException(const std::exception& e);
+
+ protected:
+ /* AsyncJob API */
+ virtual void start();
+ virtual void swanSong();
+ virtual bool doneAll() const;
+
+ virtual void cleanup(); ///< perform cleanup actions
+ virtual void handleError();
+ virtual void handleTimeout();
+ virtual void handleException(const std::exception& e);
+ virtual void handleRemoteAck();
+
+ private:
+ static void RequestTimedOut(void* param);
+ void requestTimedOut();
+ void removeTimeoutEvent();
+ static AsyncCall::Pointer DequeueRequest(unsigned int requestId);
+
+ protected:
+ Request::Pointer request;
+ const double timeout; ///< response wait timeout in seconds
+
+ /// maps request->id to Forwarder::handleRemoteAck callback
+ typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
+ static RequestsMap TheRequestsMap; ///< pending Coordinator requests
+
+ static unsigned int LastRequestId; ///< last requestId used
+
+ CBDATA_CLASS2(Forwarder);
+ };
+
+ } // namespace Ipc
+
+ #endif /* SQUID_IPC_FORWARDER_H */
--- /dev/null
+ /*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+ #include "config.h"
+ #include "base/TextException.h"
++#include "comm.h"
+ #include "comm/Write.h"
+ #include "ipc/Inquirer.h"
+ #include "ipc/Port.h"
+ #include "ipc/TypedMsgHdr.h"
+ #include "MemBuf.h"
+ #include <algorithm>
+
+
+ CBDATA_NAMESPACED_CLASS_INIT(Ipc, Inquirer);
+
+ Ipc::Inquirer::RequestsMap Ipc::Inquirer::TheRequestsMap;
+ unsigned int Ipc::Inquirer::LastRequestId = 0;
+
+ /// compare Ipc::StrandCoord using kidId, for std::sort() below
+ static bool
+ LesserStrandByKidId(const Ipc::StrandCoord &c1, const Ipc::StrandCoord &c2)
+ {
+ return c1.kidId < c2.kidId;
+ }
+
+ Ipc::Inquirer::Inquirer(Request::Pointer aRequest, const StrandCoords& coords,
+ double aTimeout):
+ AsyncJob("Ipc::Inquirer"),
+ request(aRequest), strands(coords), pos(strands.begin()), timeout(aTimeout)
+ {
+ debugs(54, 5, HERE);
+
+ // order by ascending kid IDs; useful for non-aggregatable stats
+ std::sort(strands.begin(), strands.end(), LesserStrandByKidId);
+ }
+
+ Ipc::Inquirer::~Inquirer()
+ {
+ debugs(54, 5, HERE);
+ cleanup();
+ }
+
+ void
+ Ipc::Inquirer::cleanup()
+ {
+ }
+
+ void
+ Ipc::Inquirer::start()
+ {
+ request->requestId = 0;
+ }
+
+ void
+ Ipc::Inquirer::inquire()
+ {
+ if (pos == strands.end()) {
+ Must(done());
+ return;
+ }
+
+ Must(request->requestId == 0);
+ AsyncCall::Pointer callback = asyncCall(54, 5, "Mgr::Inquirer::handleRemoteAck",
+ HandleAckDialer(this, &Inquirer::handleRemoteAck, NULL));
+ if (++LastRequestId == 0) // don't use zero value as request->requestId
+ ++LastRequestId;
+ request->requestId = LastRequestId;
+ const int kidId = pos->kidId;
+ debugs(54, 4, HERE << "inquire kid: " << kidId << status());
+ TheRequestsMap[request->requestId] = callback;
+ TypedMsgHdr message;
+ request->pack(message);
+ SendMessage(Port::MakeAddr(strandAddrPfx, kidId), message);
+ eventAdd("Ipc::Inquirer::requestTimedOut", &Inquirer::RequestTimedOut,
+ this, timeout, 0, false);
+ }
+
+ /// called when a strand is done writing its output
+ void
+ Ipc::Inquirer::handleRemoteAck(Response::Pointer response)
+ {
+ debugs(54, 4, HERE << status());
+ request->requestId = 0;
+ removeTimeoutEvent();
+ if (aggregate(response)) {
+ Must(!done()); // or we should not be called
+ ++pos; // advance after a successful inquiry
+ inquire();
+ } else {
+ mustStop("error");
+ }
+ }
+
+ void
+ Ipc::Inquirer::swanSong()
+ {
+ debugs(54, 5, HERE);
+ removeTimeoutEvent();
+ if (request->requestId > 0) {
+ DequeueRequest(request->requestId);
+ request->requestId = 0;
+ }
+ sendResponse();
+ cleanup();
+ }
+
+ bool
+ Ipc::Inquirer::doneAll() const
+ {
+ return pos == strands.end();
+ }
+
+ void
+ Ipc::Inquirer::handleException(const std::exception& e)
+ {
+ debugs(54, 3, HERE << e.what());
+ mustStop("exception");
+ }
+
+ void
+ Ipc::Inquirer::callException(const std::exception& e)
+ {
+ debugs(54, 3, HERE);
+ try {
+ handleException(e);
+ } catch (const std::exception& ex) {
+ debugs(54, DBG_CRITICAL, HERE << ex.what());
+ }
+ AsyncJob::callException(e);
+ }
+
+ /// returns and forgets the right Inquirer callback for strand request
+ AsyncCall::Pointer
+ Ipc::Inquirer::DequeueRequest(unsigned int requestId)
+ {
+ debugs(54, 3, HERE << " requestId " << requestId);
+ Must(requestId != 0);
+ AsyncCall::Pointer call;
+ RequestsMap::iterator request = TheRequestsMap.find(requestId);
+ if (request != TheRequestsMap.end()) {
+ call = request->second;
+ Must(call != NULL);
+ TheRequestsMap.erase(request);
+ }
+ return call;
+ }
+
+ void
+ Ipc::Inquirer::HandleRemoteAck(const Response& response)
+ {
+ Must(response.requestId != 0);
+ AsyncCall::Pointer call = DequeueRequest(response.requestId);
+ if (call != NULL) {
+ HandleAckDialer* dialer = dynamic_cast<HandleAckDialer*>(call->getDialer());
+ Must(dialer);
+ dialer->arg1 = response.clone();
+ ScheduleCallHere(call);
+ }
+ }
+
+ /// called when we are no longer waiting for the strand to respond
+ void
+ Ipc::Inquirer::removeTimeoutEvent()
+ {
+ if (eventFind(&Inquirer::RequestTimedOut, this))
+ eventDelete(&Inquirer::RequestTimedOut, this);
+ }
+
+ /// Ipc::Inquirer::requestTimedOut wrapper
+ void
+ Ipc::Inquirer::RequestTimedOut(void* param)
+ {
+ debugs(54, 3, HERE);
+ Must(param != NULL);
+ Inquirer* cmi = static_cast<Inquirer*>(param);
+ // use async call to enable job call protection that time events lack
+ CallJobHere(54, 5, cmi, Inquirer, requestTimedOut);
+ }
+
+ /// called when the strand failed to respond (or finish responding) in time
+ void
+ Ipc::Inquirer::requestTimedOut()
+ {
+ debugs(54, 3, HERE);
+ if (request->requestId != 0) {
+ DequeueRequest(request->requestId);
+ request->requestId = 0;
+ Must(!done()); // or we should not be called
+ ++pos; // advance after a failed inquiry
+ inquire();
+ }
+ }
+
+ const char*
+ Ipc::Inquirer::status() const
+ {
+ static MemBuf buf;
+ buf.reset();
+ buf.Printf(" [request->requestId %u]", request->requestId);
+ buf.terminate();
+ return buf.content();
+ }
*
*/
+
#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";
*/
#include "config.h"
- #include "base/TextException.h"
+ #include <map>
#include "comm.h"
+ #include "base/TextException.h"
+#include "comm/Connection.h"
#include "ipc/Port.h"
#include "ipc/Messages.h"
#include "ipc/Kids.h"
#include "ipc/StartListening.h"
#include "ipc/SharedListen.h"
- #include <map>
--
/// holds information necessary to handle JoinListen response
class PendingOpenRequest
{
#ifndef SQUID_IPC_START_LISTENING_H
#define SQUID_IPC_START_LISTENING_H
- #include "base/AsyncCall.h"
+#include "base/Subscription.h"
+#include "comm/forward.h"
#include "ip/forward.h"
#include "ipc/FdNotes.h"
+ #include "base/AsyncCall.h"
#if HAVE_IOSFWD
#include <iosfwd>
* 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"
{
AsyncJob::Start(new UdsSender(toAddress, message));
}
-int Ipc::ImportFdIntoComm(int fd, int socktype, int protocol, Ipc::FdNoteId noteId)
+
- if (getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
- Ip::Address ipAddr(addr);
++const Comm::ConnectionPointer &
++Ipc::ImportFdIntoComm(const Comm::ConnectionPointer &conn, int socktype, int protocol, Ipc::FdNoteId noteId)
+ {
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
- ipAddr.GetAddrInfo(addr_info);
++ if (getsockname(conn->fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
++ conn->remote = addr;
+ struct addrinfo* addr_info = NULL;
- comm_import_opened(fd, ipAddr, COMM_NONBLOCKING, Ipc::FdNote(noteId), addr_info);
- ipAddr.FreeAddrInfo(addr_info);
++ conn->remote.GetAddrInfo(addr_info);
+ addr_info->ai_socktype = socktype;
+ addr_info->ai_protocol = protocol;
- debugs(54, DBG_CRITICAL, HERE << "ERROR: FD " << fd << ' ' << xstrerror());
- ::close(fd);
- fd = -1;
++ comm_import_opened(conn, Ipc::FdNote(noteId), addr_info);
++ conn->remote.FreeAddrInfo(addr_info);
+ } else {
- return fd;
++ debugs(54, DBG_CRITICAL, "ERROR: Ipc::ImportFdIntoComm: " << conn << ' ' << xstrerror());
++ conn->close();
+ }
++ return conn;
+ }
#include "SquidString.h"
#include "base/AsyncJob.h"
+#include "comm/forward.h"
#include "ipc/TypedMsgHdr.h"
+ #include "ipc/FdNotes.h"
class CommTimeoutCbParams;
class CommIoCbParams;
void SendMessage(const String& toAddress, const TypedMsgHdr& message);
-int ImportFdIntoComm(int fd, int socktype, int protocol, FdNoteId noteId);
+ /// import socket fd from another strand into our Comm state
++const Comm::ConnectionPointer & ImportFdIntoComm(const Comm::ConnectionPointer &conn, int socktype, int protocol, FdNoteId noteId);
}
#include "squid.h"
#include "AccessLogEntry.h"
- #include "acl/Acl.h"
- #include "acl/Asn.h"
+#if USE_ADAPTATION
+#include "adaptation/Config.h"
+#endif
+#if USE_ECAP
+#include "adaptation/ecap/Config.h"
+#endif
#if ICAP_CLIENT
+#include "adaptation/icap/Config.h"
#include "adaptation/icap/icap_log.h"
#endif
+ #if USE_AUTH
#include "auth/Gadgets.h"
+ #endif
+#include "base/Subscription.h"
#include "base/TextException.h"
#if USE_DELAY_POOLS
#include "ClientDelayConfig.h"
#include "event.h"
#include "EventLoop.h"
#include "ExternalACL.h"
- #include "htcp.h"
- #include "HttpReply.h"
++#include "fs/Module.h"
++#include "PeerSelectState.h"
+ #include "Store.h"
#include "ICP.h"
#include "ident/Ident.h"
- #include "ip/tools.h"
- #include "ipc/Coordinator.h"
+ #include "HttpReply.h"
+ #include "pconn.h"
+ #include "Mem.h"
+ #include "acl/Asn.h"
+ #include "acl/Acl.h"
+ #include "htcp.h"
+ #include "StoreFileSystem.h"
+ #include "DiskIO/DiskIOModule.h"
#include "ipc/Kids.h"
+ #include "ipc/Coordinator.h"
#include "ipc/Strand.h"
-
- #include "DiskIO/DiskIOModule.h"
- #if USE_SQUID_ESI
- #include "esi/Module.h"
- #endif
+ #include "ip/tools.h"
+ #include "SquidTime.h"
+ #include "SwapDir.h"
#include "forward.h"
- #include "fs/Module.h"
+ #include "MemPool.h"
#include "icmp/IcmpSquid.h"
#include "icmp/net_db.h"
+
#if USE_LOADABLE_MODULES
#include "LoadableModules.h"
#endif
*/
#include "config.h"
++#include "comm/Connection.h"
#include "HttpReply.h"
#include "ipc/Port.h"
#include "mgr/ActionCreator.h"
// 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);
}
#include "config.h"
#include "base/AsyncJobCalls.h"
#include "base/TextException.h"
- #include "comm/Connection.h"
#include "CommCalls.h"
++#include "comm/Connection.h"
#include "errorpage.h"
#include "HttpReply.h"
#include "HttpRequest.h"
CBDATA_NAMESPACED_CLASS_INIT(Mgr, Forwarder);
- Mgr::Forwarder::RequestsMap Mgr::Forwarder::TheRequestsMap;
- unsigned int Mgr::Forwarder::LastRequestId = 0;
- Mgr::Forwarder::Forwarder(const Comm::ConnectionPointer &conn, const ActionParams &aParams,
-Mgr::Forwarder::Forwarder(int aFd, const ActionParams &aParams,
++Mgr::Forwarder::Forwarder(const Comm::ConnectionPointer &aConn, const ActionParams &aParams,
HttpRequest* aRequest, StoreEntry* anEntry):
- AsyncJob("Mgr::Forwarder"),
- params(aParams),
- request(aRequest), entry(anEntry), clientConnection(conn), requestId(0), closer(NULL)
- Ipc::Forwarder(new Request(KidIdentifier, 0, aFd, aParams), 10),
- httpRequest(aRequest), entry(anEntry), fd(aFd)
++ Ipc::Forwarder(new Request(KidIdentifier, 0, aConn, aParams), 10),
++ httpRequest(aRequest), entry(anEntry), conn(aConn)
{
- debugs(16, 5, HERE << clientConnection);
- Must(Comm::IsConnOpen(clientConnection));
- Must(request != NULL);
- debugs(16, 5, HERE << "FD " << fd);
- Must(fd >= 0);
++ debugs(16, 5, HERE << conn);
++ Must(Comm::IsConnOpen(conn));
+ Must(httpRequest != NULL);
Must(entry != NULL);
- HTTPMSGLOCK(request);
+ HTTPMSGLOCK(httpRequest);
entry->lock();
EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT);
closer = asyncCall(16, 5, "Mgr::Forwarder::noteCommClosed",
CommCbMemFunT<Forwarder, CommCloseCbParams>(this, &Forwarder::noteCommClosed));
- comm_add_close_handler(clientConnection->fd, closer);
- comm_add_close_handler(fd, closer);
++ comm_add_close_handler(conn->fd, closer);
}
Mgr::Forwarder::~Forwarder()
/// closes our copy of the client HTTP connection socket
void
- Mgr::Forwarder::close()
+ Mgr::Forwarder::cleanup()
{
- if (Comm::IsConnOpen(clientConnection)) {
- if (fd >= 0) {
++ if (Comm::IsConnOpen(conn)) {
if (closer != NULL) {
- comm_remove_close_handler(clientConnection->fd, closer);
- comm_remove_close_handler(fd, closer);
++ comm_remove_close_handler(conn->fd, closer);
closer = NULL;
}
- clientConnection->close();
- comm_close(fd);
- fd = -1;
++ conn->close();
}
++ conn = NULL;
}
void
}
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");
}
#ifndef SQUID_MGR_FORWARDER_H
#define SQUID_MGR_FORWARDER_H
- #include "base/AsyncJob.h"
+#include "comm/forward.h"
+ #include "ipc/Forwarder.h"
#include "mgr/ActionParams.h"
- #include <map>
class CommCloseCbParams;
* Waits for an ACK from Coordinator while holding the Store entry.
* Fills the store entry with an error response if forwarding fails.
*/
- class Forwarder: public AsyncJob
+ class Forwarder: public Ipc::Forwarder
{
public:
- Forwarder(const Comm::ConnectionPointer &conn, const ActionParams &aParams, HttpRequest* aRequest,
- Forwarder(int aFd, const ActionParams &aParams, HttpRequest* aRequest,
++ Forwarder(const Comm::ConnectionPointer &aConn, const ActionParams &aParams, HttpRequest* aRequest,
StoreEntry* anEntry);
virtual ~Forwarder();
- /// finds and calls the right Forwarder upon Coordinator's response
- static void HandleRemoteAck(unsigned int requestId);
-
- /* has-to-be-public AsyncJob API */
- virtual void callException(const std::exception& e);
-
protected:
- /* AsyncJob API */
- virtual void start();
- virtual void swanSong();
- virtual bool doneAll() const;
+ /* Ipc::Forwarder API */
+ virtual void cleanup(); ///< perform cleanup actions
+ virtual void handleError();
+ virtual void handleTimeout();
+ virtual void handleException(const std::exception& e);
+ virtual void handleRemoteAck();
private:
- void handleRemoteAck();
- static void RequestTimedOut(void* param);
- void requestTimedOut();
- void quitOnError(const char *reason, ErrorState *error);
void noteCommClosed(const CommCloseCbParams& params);
- void removeTimeoutEvent();
- static AsyncCall::Pointer DequeueRequest(unsigned int requestId);
- static void Abort(void* param);
- void close();
+ void sendError(ErrorState* error);
private:
- ActionParams params; ///< action parameters to pass to the other side
- HttpRequest* request; ///< HTTP client request for detailing errors
+ HttpRequest* httpRequest; ///< HTTP client request for detailing errors
StoreEntry* entry; ///< Store entry expecting the response
- Comm::ConnectionPointer clientConnection; ///< HTTP client connection descriptor
- unsigned int requestId; ///< request id
- int fd; ///< HTTP client connection descriptor
++ Comm::ConnectionPointer conn; ///< HTTP client connection descriptor
AsyncCall::Pointer closer; ///< comm_close handler for the HTTP connection
- /// maps requestId to Forwarder::handleRemoteAck callback
- typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
- static RequestsMap TheRequestsMap; ///< pending Coordinator requests
-
- static unsigned int LastRequestId; ///< last requestId used
-
CBDATA_CLASS2(Forwarder);
};
#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"
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
#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"
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
#include "config.h"
#include "base/TextException.h"
- #include "comm.h"
++#include "comm/Connection.h"
#include "comm/Write.h"
#include "CommCalls.h"
- #include "comm/Connection.h"
#include "HttpReply.h"
- #include "ipc/Coordinator.h"
+ #include "HttpRequest.h"
+ #include "ipc/UdsOp.h"
#include "mgr/ActionWriter.h"
- #include "mgr/Command.h"
+ #include "mgr/IntParam.h"
#include "mgr/Inquirer.h"
+ #include "mgr/Command.h"
#include "mgr/Request.h"
#include "mgr/Response.h"
#include "SquidTime.h"
CBDATA_NAMESPACED_CLASS_INIT(Mgr, Inquirer);
- Mgr::Inquirer::RequestsMap Mgr::Inquirer::TheRequestsMap;
- unsigned int Mgr::Inquirer::LastRequestId = 0;
-
- /// compare Ipc::StrandCoord using kidId, for std::sort() below
- static bool
- LesserStrandByKidId(const Ipc::StrandCoord &c1, const Ipc::StrandCoord &c2)
- {
- return c1.kidId < c2.kidId;
- }
- Mgr::Inquirer::Inquirer(Action::Pointer anAction, const Comm::ConnectionPointer &conn,
+ Mgr::Inquirer::Inquirer(Action::Pointer anAction,
const Request &aCause, const Ipc::StrandCoords &coords):
- AsyncJob("Mgr::Inquirer"),
- aggrAction(anAction),
- cause(aCause),
- clientConnection(conn),
- strands(coords), pos(strands.begin()),
- requestId(0), closer(NULL), timeout(aggrAction->atomic() ? 10 : 100)
+ Ipc::Inquirer(aCause.clone(), applyQueryParams(coords, aCause.params.queryParams), anAction->atomic() ? 10 : 100),
- aggrAction(anAction),
- fd(Ipc::ImportFdIntoComm(aCause.fd, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket))
++ aggrAction(anAction)
{
- debugs(16, 5, HERE << conn << " action: " << aggrAction);
- debugs(16, 5, HERE << "FD " << fd << " action: " << aggrAction);
++ conn = aCause.conn;
++ Ipc::ImportFdIntoComm(conn, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket);
+
- // order by ascending kid IDs; useful for non-aggregatable stats
- std::sort(strands.begin(), strands.end(), LesserStrandByKidId);
++ debugs(16, 5, HERE << conn << " action: " << aggrAction);
closer = asyncCall(16, 5, "Mgr::Inquirer::noteCommClosed",
CommCbMemFunT<Inquirer, CommCloseCbParams>(this, &Inquirer::noteCommClosed));
- comm_add_close_handler(clientConnection->fd, closer);
- }
-
- Mgr::Inquirer::~Inquirer()
- {
- debugs(16, 5, HERE);
- close();
- comm_add_close_handler(fd, closer);
++ comm_add_close_handler(conn->fd, closer);
}
/// closes our copy of the client HTTP connection socket
void
- Mgr::Inquirer::close()
+ Mgr::Inquirer::cleanup()
{
- if (Comm::IsConnOpen(clientConnection)) {
- if (fd >= 0) {
++ if (Comm::IsConnOpen(conn)) {
removeCloseHandler();
- clientConnection->close();
- comm_close(fd);
- fd = -1;
++ conn->close();
}
}
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;
}
}
Mgr::Inquirer::start()
{
debugs(16, 5, HERE);
- Must(Comm::IsConnOpen(clientConnection));
+ Ipc::Inquirer::start();
- Must(fd >= 0);
++ Must(Comm::IsConnOpen(conn));
Must(aggrAction != NULL);
- std::auto_ptr<HttpReply> reply(new HttpReply);
- reply->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime);
- reply->header.putStr(HDR_CONNECTION, "close"); // until we chunk response
- std::auto_ptr<MemBuf> replyBuf(reply->pack());
+ std::auto_ptr<MemBuf> replyBuf;
+ if (strands.empty()) {
+ LOCAL_ARRAY(char, url, MAX_URL);
+ snprintf(url, MAX_URL, "%s", aggrAction->command().params.httpUri.termedBuf());
+ HttpRequest *req = HttpRequest::CreateFromUrl(url);
+ ErrorState *err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND, req);
+ std::auto_ptr<HttpReply> reply(err->BuildHttpReply());
+ replyBuf.reset(reply->pack());
+ errorStateFree(err);
+ } else {
+ std::auto_ptr<HttpReply> reply(new HttpReply);
+ reply->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime);
+ reply->header.putStr(HDR_CONNECTION, "close"); // until we chunk response
+ replyBuf.reset(reply->pack());
+ }
writer = asyncCall(16, 5, "Mgr::Inquirer::noteWroteHeader",
CommCbMemFunT<Inquirer, CommIoCbParams>(this, &Inquirer::noteWroteHeader));
- Comm::Write(clientConnection, replyBuf.get(), writer);
- Comm::Write(fd, replyBuf.get(), writer);
++ Comm::Write(conn, replyBuf.get(), writer);
}
/// called when we wrote the response header
debugs(16, 5, HERE);
writer = NULL;
Must(params.flag == COMM_OK);
- Must(clientConnection != NULL && params.fd == clientConnection->fd);
- Must(params.fd == fd);
++ Must(params.conn.getRaw() == conn.getRaw());
Must(params.size != 0);
// start inquiries at the initial pos
inquire();
}
+ /// called when the HTTP client or some external force closed our socket
void
- Mgr::Inquirer::inquire()
+ Mgr::Inquirer::noteCommClosed(const CommCloseCbParams& params)
{
- if (pos == strands.end()) {
- Must(done());
- return;
- }
-
- Must(requestId == 0);
- AsyncCall::Pointer callback = asyncCall(16, 5, "Mgr::Inquirer::handleRemoteAck",
- HandleAckDialer(this, &Inquirer::handleRemoteAck, Response()));
- if (++LastRequestId == 0) // don't use zero value as requestId
- ++LastRequestId;
- requestId = LastRequestId;
- const int kidId = pos->kidId;
- debugs(16, 4, HERE << "inquire kid: " << kidId << status());
- TheRequestsMap[requestId] = callback;
- Request mgrRequest(KidIdentifier, requestId, clientConnection,
- aggrAction->command().params);
- Ipc::TypedMsgHdr message;
- mgrRequest.pack(message);
- Ipc::SendMessage(Ipc::Port::MakeAddr(Ipc::strandAddrPfx, kidId), message);
- eventAdd("Mgr::Inquirer::requestTimedOut", &Inquirer::RequestTimedOut,
- this, timeout, 0, false);
+ debugs(16, 5, HERE);
- Must(fd < 0 || fd == params.fd);
- fd = -1;
++ Must(!Comm::IsConnOpen(conn) && params.conn.getRaw() == conn.getRaw());
++ conn = NULL;
+ mustStop("commClosed");
}
- /// called when a strand is done writing its output
- void
- Mgr::Inquirer::handleRemoteAck(const Response& response)
+ bool
+ Mgr::Inquirer::aggregate(Ipc::Response::Pointer aResponse)
{
- debugs(16, 4, HERE << status());
- requestId = 0;
- removeTimeoutEvent();
+ Mgr::Response& response = static_cast<Response&>(*aResponse);
if (response.hasAction())
aggrAction->add(response.getAction());
- Must(!done()); // or we should not be called
- ++pos; // advance after a successful inquiry
- inquire();
- }
-
- /// called when the HTTP client or some external force closed our socket
- void
- Mgr::Inquirer::noteCommClosed(const CommCloseCbParams& params)
- {
- debugs(16, 5, HERE);
- Must(!Comm::IsConnOpen(clientConnection) || clientConnection->fd == params.fd);
- clientConnection = NULL; // AYJ: Do we actually have to NULL it?
- mustStop("commClosed");
+ return true;
}
void
- Mgr::Inquirer::swanSong()
+ Mgr::Inquirer::sendResponse()
{
- debugs(16, 5, HERE);
- removeTimeoutEvent();
- if (requestId > 0) {
- DequeueRequest(requestId);
- requestId = 0;
- }
- if (aggrAction->aggregatable()) {
+ if (!strands.empty() && aggrAction->aggregatable()) {
removeCloseHandler();
- AsyncJob::Start(new ActionWriter(aggrAction, clientConnection));
- clientConnection = NULL; // should not close fd because we passed it to ActionWriter
- AsyncJob::Start(new ActionWriter(aggrAction, fd));
- fd = -1; // should not close fd because we passed it to ActionWriter
++ AsyncJob::Start(new ActionWriter(aggrAction, conn));
++ conn = NULL; // should not close because we passed it to ActionWriter
}
- close();
}
bool
#ifndef SQUID_MGR_INQUIRER_H
#define SQUID_MGR_INQUIRER_H
- #include "base/AsyncJobCalls.h"
- #include "base/AsyncJob.h"
+#include "comm/forward.h"
- #include "ipc/StrandCoords.h"
- #include "MemBuf.h"
+ #include "ipc/Inquirer.h"
#include "mgr/Action.h"
- #include "mgr/Request.h"
- #include <map>
class CommIoCbParams;
class CommCloseCbParams;
private:
Action::Pointer aggrAction; //< action to aggregate
- Request cause; ///< cache manager request received from HTTP client
- Comm::ConnectionPointer clientConnection; ///< HTTP client socket descriptor
-
- Ipc::StrandCoords strands; ///< all strands we want to query, in order
- Ipc::StrandCoords::const_iterator pos; ///< strand we should query now
- int fd; ///< HTTP client socket descriptor
++ Comm::ConnectionPointer conn; ///< HTTP client socket descriptor
- unsigned int requestId; ///< ID of our outstanding request to strand
AsyncCall::Pointer writer; ///< comm_write callback
AsyncCall::Pointer closer; ///< comm_close handler
- const double timeout; ///< number of seconds to wait for strand response
-
- /// maps requestId to Inquirer::handleRemoteAck callback
- typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
- static RequestsMap TheRequestsMap; ///< pending strand requests
-
- static unsigned int LastRequestId; ///< last requestId used
CBDATA_CLASS2(Inquirer);
};
#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
msg.putPod(requestId);
params.pack(msg);
-- msg.putFd(fd);
++ msg.putFd(conn->fd);
+ }
+
+ Ipc::Request::Pointer
+ Mgr::Request::clone() const
+ {
+ return new Request(*this);
}
{
/// 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
};
Mgr::StoreToCommWriter::Abort(void* param)
{
StoreToCommWriter* mgrWriter = static_cast<StoreToCommWriter*>(param);
- if (mgrWriter->fd >= 0)
- comm_close(mgrWriter->fd);
+ if (Comm::IsConnOpen(mgrWriter->clientConnection))
+ mgrWriter->clientConnection->close();
}
-
- Comm::ConnectionPointer
- Mgr::ImportHttpFdIntoComm(int fd)
- {
- Comm::ConnectionPointer result = new Comm::Connection();
- struct sockaddr_in addr;
- socklen_t len = sizeof(addr);
- if (getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
- result->fd = fd;
- result->local = addr;
- struct addrinfo* addr_info = NULL;
- result->local.GetAddrInfo(addr_info);
- addr_info->ai_socktype = SOCK_STREAM;
- addr_info->ai_protocol = IPPROTO_TCP;
- comm_import_opened(result, Ipc::FdNote(Ipc::fdnHttpSocket), addr_info);
- result->local.FreeAddrInfo(addr_info);
- } else {
- debugs(16, DBG_CRITICAL, HERE << "ERROR: FD " << fd << ' ' << xstrerror());
- ::close(fd);
- fd = -1;
- }
- return result;
- }
mcastJoinGroups(const ipcache_addrs *ia, const DnsLookupDetails &, void *datanotused)
{
#ifdef IP_MULTICAST_TTL
- int fd = theInIcpConnection;
-
+ struct ip_mreq mr;
+ int i;
- int x;
- char c = 0;
if (ia == NULL) {
- debugs(7, DBG_CRITICAL, "ERROR: Attempting to join multicast group. Cannot resolve group hostname in DNS.");
+ debugs(7, 0, "comm_join_mcast_groups: Unknown host");
return;
}
continue;
}
- struct ip_mreq mr;
ia->in_addrs[i].GetInAddr(mr.imr_multiaddr);
+
mr.imr_interface.s_addr = INADDR_ANY;
- x = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char *) &mr, sizeof(struct ip_mreq));
-
- if (x < 0)
- debugs(7, 1, "comm_join_mcast_groups: FD " << fd << ", IP=" << ia->in_addrs[i]);
- x = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1);
+ if (setsockopt(icpIncomingConn->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mr, sizeof(struct ip_mreq)) < 0)
+ debugs(7, DBG_IMPORTANT, "ERROR: Join failed for " << icpIncomingConn << ", Multicast IP=" << ia->in_addrs[i]);
- if (x < 0)
- debugs(7, 1, "Can't disable multicast loopback: " << xstrerror());
+ char c = 0;
+ if (setsockopt(icpIncomingConn->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1) < 0)
+ debugs(7, DBG_IMPORTANT, "ERROR: " << icpIncomingConn << " can't disable multicast loopback: " << xstrerror());
}
#endif
*/
#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 */
*/
#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;
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
psstate->request = HTTPMSGLOCK(request);
psstate->entry = entry;
-
+ psstate->paths = paths;
psstate->callback = callback;
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)
{
*/
#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"
else
r->client_addr.SetNoAddr();
r->client_ident = NULL;
-
+ #if USE_AUTH
if (http->request->auth_user_request != NULL)
r->client_ident = http->request->auth_user_request->username();
- else if (http->request->extacl_user.defined()) {
- r->client_ident = http->request->extacl_user.termedBuf();
- }
+ else
+ #endif
+ if (http->request->extacl_user.defined()) {
+ r->client_ident = http->request->extacl_user.termedBuf();
+ }
- if (!r->client_ident && (conn != NULL && conn->rfc931[0]))
- r->client_ident = conn->rfc931;
+ if (!r->client_ident && conn != NULL && conn->clientConnection != NULL && conn->clientConnection->rfc931[0])
+ r->client_ident = conn->clientConnection->rfc931;
#if USE_SSL
if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL)
fqdn = dash_str;
- snprintf(buf, 8192, "%s %s/%s %s %s myip=%s myport=%d\n",
- r->orig_url,
- r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
- fqdn,
- r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
- r->method_s,
- http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
- http->request->my_addr.GetPort());
+ sz = snprintf(buf, MAX_REDIRECTOR_REQUEST_STRLEN, "%s %s/%s %s %s myip=%s myport=%d\n",
+ r->orig_url,
+ r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
+ fqdn,
+ r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
+ r->method_s,
+ http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
+ http->request->my_addr.GetPort());
+
+ if ((sz<=0) || (sz>=MAX_REDIRECTOR_REQUEST_STRLEN)) {
+ if (sz<=0) {
+ status = HTTP_INTERNAL_SERVER_ERROR;
+ debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Can not build request to be passed to redirector. Request ABORTED.");
+ } else {
+ status = HTTP_REQUEST_URI_TOO_LARGE;
+ debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Request passed to redirector exceeds MAX_REDIRECTOR_REQUEST_STRLEN (" << MAX_REDIRECTOR_REQUEST_STRLEN << "). Request ABORTED.");
+ }
+
+ clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data;
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ Ip::Address tmpnoaddr;
+ tmpnoaddr.SetNoAddr();
+ repContext->setReplyToError(ERR_GATEWAY_FAILURE, status,
+ http->request->method, NULL,
- http->getConn() != NULL ? http->getConn()->peer : tmpnoaddr,
++ http->getConn() != NULL && http->getConn()->clientConnection != NULL ?
++ http->getConn()->clientConnection->remote : tmpnoaddr,
+ http->request,
+ NULL,
+ #if USE_AUTH
+ http->getConn() != NULL && http->getConn()->auth_user_request != NULL ?
+ http->getConn()->auth_user_request : http->request->auth_user_request);
+ #else
+ NULL);
+ #endif
+
+ node = (clientStreamNode *)http->client_stream.tail->data;
+ clientStreamRead(node, http, node->readBuffer);
+ return;
+ }
helperSubmit(redirectors, buf, redirectHandleReply, r);
}
--- /dev/null
+ /*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+ #include "config.h"
+ #include "base/TextException.h"
+ #include "CommCalls.h"
++#include "comm.h"
+ #include "ipc/Port.h"
+ #include "snmp_core.h"
+ #include "snmp/Forwarder.h"
+ #include "snmp/Request.h"
+ #include "snmp/Response.h"
+
+
+ CBDATA_NAMESPACED_CLASS_INIT(Snmp, Forwarder);
+
+
+ Snmp::Forwarder::Forwarder(const Pdu& aPdu, const Session& aSession, int aFd,
+ const Ip::Address& anAddress):
+ Ipc::Forwarder(new Request(KidIdentifier, 0, aPdu, aSession, aFd, anAddress), 2),
+ fd(aFd)
+ {
+ debugs(49, 5, HERE << "FD " << aFd);
+ Must(fd >= 0);
+ closer = asyncCall(49, 5, "Snmp::Forwarder::noteCommClosed",
+ CommCbMemFunT<Forwarder, CommCloseCbParams>(this, &Forwarder::noteCommClosed));
+ comm_add_close_handler(fd, closer);
+ }
+
+ /// removes our cleanup handler of the client connection socket
+ void
+ Snmp::Forwarder::cleanup()
+ {
+ if (fd >= 0) {
+ if (closer != NULL) {
+ comm_remove_close_handler(fd, closer);
+ closer = NULL;
+ }
+ fd = -1;
+ }
+ }
+
+ /// called when the client socket gets closed by some external force
+ void
+ Snmp::Forwarder::noteCommClosed(const CommCloseCbParams& params)
+ {
+ debugs(49, 5, HERE);
+ Must(fd == params.fd);
+ fd = -1;
+ mustStop("commClosed");
+ }
+
+ void
+ Snmp::Forwarder::handleTimeout()
+ {
+ sendError(SNMP_ERR_RESOURCEUNAVAILABLE);
+ Ipc::Forwarder::handleTimeout();
+ }
+
+ void
+ Snmp::Forwarder::handleException(const std::exception& e)
+ {
+ debugs(49, 3, HERE << e.what());
+ if (fd >= 0)
+ sendError(SNMP_ERR_GENERR);
+ Ipc::Forwarder::handleException(e);
+ }
+
+ /// send error SNMP response
+ void
+ Snmp::Forwarder::sendError(int error)
+ {
+ debugs(49, 3, HERE);
+ Snmp::Request& req = static_cast<Snmp::Request&>(*request);
+ req.pdu.command = SNMP_PDU_RESPONSE;
+ req.pdu.errstat = error;
+ u_char buffer[SNMP_REQUEST_SIZE];
+ int len = sizeof(buffer);
+ snmp_build(&req.session, &req.pdu, buffer, &len);
+ comm_udp_sendto(fd, req.address, buffer, len);
+ }
+
+ void
+ Snmp::SendResponse(unsigned int requestId, const Pdu& pdu)
+ {
+ debugs(49, 5, HERE);
+ // snmpAgentResponse() can modify arg
+ Pdu tmp = pdu;
+ Snmp::Response response(requestId);
+ snmp_pdu* response_pdu = NULL;
+ try {
+ response_pdu = snmpAgentResponse(&tmp);
+ Must(response_pdu != NULL);
+ response.pdu = static_cast<Pdu&>(*response_pdu);
+ snmp_free_pdu(response_pdu);
+ } catch (const std::exception& e) {
+ debugs(49, DBG_CRITICAL, HERE << e.what());
+ response.pdu.command = SNMP_PDU_RESPONSE;
+ response.pdu.errstat = SNMP_ERR_GENERR;
+ }
+ Ipc::TypedMsgHdr message;
+ response.pack(message);
+ Ipc::SendMessage(Ipc::coordinatorAddr, message);
+ }
--- /dev/null
- aggrPdu(aRequest.pdu),
- fd(ImportFdIntoComm(aRequest.fd, SOCK_DGRAM, IPPROTO_UDP, Ipc::fdnInSnmpSocket))
+ /*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+ #include "config.h"
+ #include "base/TextException.h"
+ #include "CommCalls.h"
++#include "comm.h"
++#include "comm/Connection.h"
+ #include "ipc/UdsOp.h"
+ #include "snmp_core.h"
+ #include "snmp/Inquirer.h"
+ #include "snmp/Response.h"
+ #include "snmp/Request.h"
+
+
+ CBDATA_NAMESPACED_CLASS_INIT(Snmp, Inquirer);
+
+
+ Snmp::Inquirer::Inquirer(const Request& aRequest, const Ipc::StrandCoords& coords):
+ Ipc::Inquirer(aRequest.clone(), coords, 2),
- comm_add_close_handler(fd, closer);
++ aggrPdu(aRequest.pdu)
+ {
++ conn = new Comm::Connection;
++ conn->fd = aRequest.fd;
++ ImportFdIntoComm(conn, SOCK_DGRAM, IPPROTO_UDP, Ipc::fdnInSnmpSocket);
++
+ debugs(49, 5, HERE);
+ closer = asyncCall(49, 5, "Snmp::Inquirer::noteCommClosed",
+ CommCbMemFunT<Inquirer, CommCloseCbParams>(this, &Inquirer::noteCommClosed));
- if (fd >= 0) {
++ comm_add_close_handler(conn->fd, closer);
+ }
+
+ /// closes our copy of the client connection socket
+ void
+ Snmp::Inquirer::cleanup()
+ {
- comm_remove_close_handler(fd, closer);
++ if (Comm::IsConnOpen(conn)) {
+ if (closer != NULL) {
- comm_close(fd);
- fd = -1;
++ comm_remove_close_handler(conn->fd, closer);
+ closer = NULL;
+ }
- Must(fd >= 0);
++ conn->close();
+ }
++ conn = NULL;
+ }
+
+ void
+ Snmp::Inquirer::start()
+ {
+ debugs(49, 5, HERE);
+ Ipc::Inquirer::start();
- Must(fd < 0 || fd == params.fd);
- fd = -1;
++ Must(Comm::IsConnOpen(conn));
+ inquire();
+ }
+
+ void
+ Snmp::Inquirer::handleException(const std::exception& e)
+ {
+ aggrPdu.errstat = SNMP_ERR_GENERR;
+ Ipc::Inquirer::handleException(e);
+ }
+
+ bool
+ Snmp::Inquirer::aggregate(Response::Pointer aResponse)
+ {
+ Snmp::Response& response = static_cast<Snmp::Response&>(*aResponse);
+ bool error = response.pdu.errstat != SNMP_ERR_NOERROR;
+ if (error) {
+ aggrPdu = response.pdu;
+ } else {
+ aggrPdu.aggregate(response.pdu);
+ }
+ return !error;
+ }
+
+ /// called when the some external force closed our socket
+ void
+ Snmp::Inquirer::noteCommClosed(const CommCloseCbParams& params)
+ {
+ debugs(49, 5, HERE);
- comm_udp_sendto(fd, req.address, buffer, len);
++ Must(!Comm::IsConnOpen(conn) || conn->fd == params.conn->fd);
++ conn = NULL;
+ mustStop("commClosed");
+ }
+
+ bool
+ Snmp::Inquirer::doneAll() const
+ {
+ return !writer && Ipc::Inquirer::doneAll();
+ }
+
+ void
+ Snmp::Inquirer::sendResponse()
+ {
+ debugs(49, 5, HERE);
+ aggrPdu.fixAggregate();
+ aggrPdu.command = SNMP_PDU_RESPONSE;
+ u_char buffer[SNMP_REQUEST_SIZE];
+ int len = sizeof(buffer);
+ Snmp::Request& req = static_cast<Snmp::Request&>(*request);
+ snmp_build(&req.session, &aggrPdu, buffer, &len);
++ comm_udp_sendto(conn->fd, req.address, buffer, len);
+ }
--- /dev/null
- int fd; ///< client connection descriptor
+ /*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+ #ifndef SQUID_SNMPX_INQUIRER_H
+ #define SQUID_SNMPX_INQUIRER_H
+
++#include "comm/forward.h"
+ #include "ipc/Inquirer.h"
+ #include "snmp/forward.h"
+ #include "snmp/Pdu.h"
+
+
+ class CommCloseCbParams;
+
+ namespace Snmp
+ {
+
+ /// Coordinator's job that sends a PDU request to each strand,
+ /// aggregates strand responses and send back the result to client
+ class Inquirer: public Ipc::Inquirer
+ {
+ public:
+ Inquirer(const Request& aRequest, const Ipc::StrandCoords& coords);
+
+ protected:
+ /* AsyncJob API */
+ virtual void start();
+ virtual bool doneAll() const;
+
+ /* Ipc::Inquirer API */
+ virtual void cleanup();
+ virtual void handleException(const std::exception& e);
+ virtual void sendResponse();
+ virtual bool aggregate(Ipc::Response::Pointer aResponse);
+
+ private:
+ void noteCommClosed(const CommCloseCbParams& params);
+
+ private:
+ Pdu aggrPdu; ///< aggregated pdu
++ Comm::ConnectionPointer conn; ///< client connection descriptor
+
+ AsyncCall::Pointer writer; ///< comm_write callback
+ AsyncCall::Pointer closer; ///< comm_close handler
+
+ CBDATA_CLASS2(Inquirer);
+ };
+
+ } // namespace Snmp
+
+ #endif /* SQUID_SNMPX_INQUIRER_H */
*/
#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"
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);
- #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 */
EXTRA_PROGRAMS = \
ssl_crtd
++EXTRA_DIST = stub_libsslsquid.cc stub_libsslutil.cc
++
if USE_SSL_CRTD
SSL_CRTD = ssl_crtd
SSL_CRTD_SOURCE = \
--- /dev/null
--- /dev/null
++#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)
--- /dev/null
--- /dev/null
++#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
#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"
(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
*/
#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;
}
/* 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
--- /dev/null
- clientdbUpdate(const Ip::Address &, log_type, protocol_t, size_t)
+#include "config.h"
+/* because the clientdb API is defined in protos.h still */
+#include "protos.h"
+
+void
+clientdbInit(void)
+{
+ fatal("client_db.cc required");
+}
+
+void
++clientdbUpdate(const Ip::Address &, log_type, AnyP::ProtocolType, size_t)
+{
+ fatal("client_db.cc required");
+}
+
+int
+clientdbCutoffDenied(const Ip::Address &)
+{
+ fatal("client_db.cc required");
+ return -1;
+}
+
+void
+clientdbDump(StoreEntry *)
+{
+ fatal("client_db.cc required");
+}
+
+void
+clientdbFreeMemory(void)
+{
+ fatal("client_db.cc required");
+}
+
+int
+clientdbEstablished(const Ip::Address &, int)
+{
+ fatal("client_db.cc required");
+ return -1;
+}
+
+#if USE_DELAY_POOLS
+void
+clientdbSetWriteLimiter(ClientInfo * info, const int writeSpeedLimit,const double initialBurst,const double highWatermark)
+{
+ fatal("client_db.cc required");
+}
+
+ClientInfo *
+clientdbGetInfo(const Ip::Address &addr)
+{
+ fatal("client_db.cc required");
+ return NULL;
+}
+#endif
+
+void
+clientOpenListenSockets(void)
+{
+ fatal("client_db.cc required");
+}
+
+void
+clientHttpConnectionsClose(void)
+{
+ fatal("client_db.cc required");
+}
/* for tests... ignore */
}
++#if 0
void
Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
{
{
/* for tests ... ignore */
}
++#endif
int
ignoreErrno(int ierrno)
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)
{
--- /dev/null
--- /dev/null
++#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)
--- /dev/null
--- /dev/null
++#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;
++}
- /*
- * $Id$
- *
- * DEBUG: section 20 Storage Manager
- * AUTHOR: Robert Collins
- *
- * SQUID Web Proxy Cache http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from
- * the Internet community; see the CONTRIBUTORS file for full
- * details. Many organizations have provided support for Squid's
- * development; see the SPONSORS file for full details. Squid is
- * Copyrighted (C) 2001 by the Regents of the University of
- * California; see the COPYRIGHT file for full details. Squid
- * incorporates software developed and/or copyrighted by other
- * sources; see the CREDITS file for full details.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- */
-
#include "squid.h"
- #include "Store.h"
- StorePointer Store::CurrentRoot = NULL;
+ #define STUB_API "store.cc"
+ #include "tests/STUB.h"
+
+ /* and code defined in the wrong .cc file */
+ #include "SwapDir.h"
+ void StoreController::maintain() STUB
+ #include "RemovalPolicy.h"
+ RemovalPolicy * createRemovalPolicy(RemovalPolicySettings * settings) STUB_RETVAL(NULL)
- extern "C" void
- storeAppendPrintf(StoreEntry * e, const char *fmt,...)
- {
- fatal("storeAppendPrintf: Not implemented");
- }
- void
- storeAppendVPrintf(StoreEntry * e, const char *fmt, va_list vargs)
+ #include "Store.h"
+ StorePointer Store::CurrentRoot = NULL;
+ StoreIoStats store_io_stats;
+ bool StoreEntry::checkDeferRead(int fd) const STUB_RETVAL(false)
+ const char *StoreEntry::getMD5Text() const STUB_RETVAL(NULL)
+ StoreEntry::StoreEntry() STUB
+ StoreEntry::StoreEntry(const char *url, const char *log_url) STUB
+ HttpReply const *StoreEntry::getReply() const STUB_RETVAL(NULL)
+ void StoreEntry::write(StoreIOBuffer) STUB
+ bool StoreEntry::isAccepting() const STUB_RETVAL(false)
+ size_t StoreEntry::bytesWanted(Range<size_t> const) const STUB_RETVAL(0)
+ void StoreEntry::complete() STUB
+ store_client_t StoreEntry::storeClientType() const STUB_RETVAL(STORE_NON_CLIENT)
+ char const *StoreEntry::getSerialisedMetaData() STUB_RETVAL(NULL)
+ void StoreEntry::replaceHttpReply(HttpReply *) STUB
+ bool StoreEntry::swapoutPossible() STUB_RETVAL(false)
+ void StoreEntry::trimMemory() STUB
+ void StoreEntry::abort() STUB
+ void StoreEntry::unlink() STUB
+ void StoreEntry::makePublic() STUB
+ void StoreEntry::makePrivate() STUB
+ void StoreEntry::setPublicKey() STUB
+ void StoreEntry::setPrivateKey() STUB
+ void StoreEntry::expireNow() STUB
+ void StoreEntry::releaseRequest() STUB
+ void StoreEntry::negativeCache() STUB
+ void StoreEntry::cacheNegatively() STUB
+ void StoreEntry::invokeHandlers() STUB
+ void StoreEntry::purgeMem() STUB
+ void StoreEntry::swapOut() STUB
+ bool StoreEntry::swapOutAble() const STUB_RETVAL(false)
+ void StoreEntry::swapOutFileClose() STUB
+ const char *StoreEntry::url() const STUB_RETVAL(NULL)
+ int StoreEntry::checkCachable() STUB_RETVAL(0)
+ int StoreEntry::checkNegativeHit() const STUB_RETVAL(0)
+ int StoreEntry::locked() const STUB_RETVAL(0)
+ int StoreEntry::validToSend() const STUB_RETVAL(0)
+ int StoreEntry::keepInMemory() const STUB_RETVAL(0)
+ void StoreEntry::createMemObject(const char *, const char *) STUB
+ void StoreEntry::dump(int debug_lvl) const STUB
+ void StoreEntry::hashDelete() STUB
+ void StoreEntry::hashInsert(const cache_key *) STUB
+ void StoreEntry::registerAbort(STABH * cb, void *) STUB
+ void StoreEntry::reset() STUB
+ void StoreEntry::setMemStatus(mem_status_t) STUB
+ void StoreEntry::timestampsSet() STUB
+ void StoreEntry::unregisterAbort() STUB
+ void StoreEntry::destroyMemObject() STUB
+ int StoreEntry::checkTooSmall() STUB_RETVAL(0)
-void StoreEntry::delayAwareRead(int fd, char *buf, int len, AsyncCall::Pointer callback) STUB
++void StoreEntry::delayAwareRead(const Comm::ConnectionPointer&, char *buf, int len, AsyncCall::Pointer callback) STUB
+ void StoreEntry::setNoDelay (bool const) STUB
+ bool StoreEntry::modifiedSince(HttpRequest * request) const STUB_RETVAL(false)
+ bool StoreEntry::hasIfMatchEtag(const HttpRequest &request) const STUB_RETVAL(false)
+ bool StoreEntry::hasIfNoneMatchEtag(const HttpRequest &request) const STUB_RETVAL(false)
+ RefCount<Store> StoreEntry::store() const STUB_RETVAL(StorePointer())
+ size_t StoreEntry::inUseCount() STUB_RETVAL(0)
+ void StoreEntry::getPublicByRequestMethod(StoreClient * aClient, HttpRequest * request, const HttpRequestMethod& method) STUB
+ void StoreEntry::getPublicByRequest(StoreClient * aClient, HttpRequest * request) STUB
+ void StoreEntry::getPublic(StoreClient * aClient, const char *uri, const HttpRequestMethod& method) STUB
+ void *StoreEntry::operator new(size_t byteCount)
{
- fatal("storeAppendVPrintf: Not implemented");
+ STUB
+ return new StoreEntry();
}
+ void StoreEntry::operator delete(void *address) STUB
+ void StoreEntry::setReleaseFlag() STUB
+ //#if USE_SQUID_ESI
+ //ESIElement::Pointer StoreEntry::cachedESITree STUB_RETVAL(NULL)
+ //#endif
+ void StoreEntry::append(char const *, int len) STUB
+ void StoreEntry::buffer() STUB
+ void StoreEntry::flush() STUB
+ int StoreEntry::unlock() STUB_RETVAL(0)
+ int64_t StoreEntry::objectLen() const STUB_RETVAL(0)
+ int64_t StoreEntry::contentLen() const STUB_RETVAL(0)
+ void StoreEntry::lock() STUB
+ void StoreEntry::release() STUB
+
+ NullStoreEntry *NullStoreEntry::getInstance() STUB_RETVAL(NULL)
+ const char *NullStoreEntry::getMD5Text() const STUB_RETVAL(NULL)
+ void NullStoreEntry::operator delete(void *address) STUB
+ // private virtual. Why is this linked from outside?
+ const char *NullStoreEntry::getSerialisedMetaData() STUB_RETVAL(NULL)
+
+ void Store::Root(Store *) STUB
+ void Store::Root(RefCount<Store>) STUB
+ void Store::Stats(StoreEntry * output) STUB
+ void Store::Maintain(void *unused) STUB
+ void Store::create() STUB
+ void Store::diskFull() STUB
+ void Store::sync() STUB
+ void Store::unlink(StoreEntry &) STUB
+
+ SQUIDCEXTERN size_t storeEntryInUse() STUB_RETVAL(0)
+ SQUIDCEXTERN const char *storeEntryFlags(const StoreEntry *) STUB_RETVAL(NULL)
+ void storeEntryReplaceObject(StoreEntry *, HttpReply *) STUB
+ SQUIDCEXTERN StoreEntry *storeGetPublic(const char *uri, const HttpRequestMethod& method) STUB_RETVAL(NULL)
+ SQUIDCEXTERN StoreEntry *storeGetPublicByRequest(HttpRequest * request) STUB_RETVAL(NULL)
+ SQUIDCEXTERN StoreEntry *storeGetPublicByRequestMethod(HttpRequest * request, const HttpRequestMethod& method) STUB_RETVAL(NULL)
+ SQUIDCEXTERN StoreEntry *storeCreateEntry(const char *, const char *, request_flags, const HttpRequestMethod&) STUB_RETVAL(NULL)
+ SQUIDCEXTERN void storeInit(void) STUB
+ SQUIDCEXTERN void storeConfigure(void) STUB
+ SQUIDCEXTERN void storeFreeMemory(void) STUB
+ SQUIDCEXTERN int expiresMoreThan(time_t, time_t) STUB_RETVAL(0)
+ SQUIDCEXTERN void storeAppendPrintf(StoreEntry *, const char *,...) STUB
+ void storeAppendVPrintf(StoreEntry *, const char *, va_list ap) STUB
+ SQUIDCEXTERN int storeTooManyDiskFilesOpen(void) STUB_RETVAL(0)
+ SQUIDCEXTERN void storeHeapPositionUpdate(StoreEntry *, SwapDir *) STUB
+ SQUIDCEXTERN void storeSwapFileNumberSet(StoreEntry * e, sfileno filn) STUB
+ SQUIDCEXTERN void storeFsInit(void) STUB
+ SQUIDCEXTERN void storeFsDone(void) STUB
+ SQUIDCEXTERN void storeReplAdd(const char *, REMOVALPOLICYCREATE *) STUB
+ void destroyStoreEntry(void *) STUB
+ // in Packer.cc !? SQUIDCEXTERN void packerToStoreInit(Packer * p, StoreEntry * e) STUB
+ SQUIDCEXTERN void storeGetMemSpace(int size) STUB
#if !_USE_INLINE_
#include "Store.cci"
*/
#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"
void
releaseServerSockets(void)
{
+ int i;
/* Release the main ports as early as possible */
- for (int i = 0; i < NHttpSockets; i++) {
+ // clear both http_port and https_port lists.
+ for (i = 0; i < NHttpSockets; i++) {
if (HttpSockets[i] >= 0)
close(HttpSockets[i]);
}
*/
#include "squid.h"
- #include "acl/FilledChecklist.h"
+ #include "errorpage.h"
+ #include "HttpRequest.h"
+ #include "fde.h"
+#include "Array.h"
#include "comm.h"
+#include "comm/Connection.h"
+#include "comm/ConnOpener.h"
#include "comm/Write.h"
- #include "client_side.h"
#include "client_side_request.h"
+ #include "acl/FilledChecklist.h"
#if USE_DELAY_POOLS
#include "DelayId.h"
#endif
- #include "errorpage.h"
- #include "fde.h"
- #include "HttpRequest.h"
- #include "http.h"
+ #include "client_side.h"
#include "MemBuf.h"
-#include "ip/tools.h"
+ #include "http.h"
+#include "PeerSelectState.h"
class TunnelStateData
{
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
/* 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);
}
*/
cbdataInternalLock(this); /* ??? should be locked by the caller... */
- /* Bump the server connection timeout on any activity */
- if (!fd_closed(server.fd()))
- commSetTimeout(server.fd(), Config.Timeout.read, tunnelTimeout, this);
+ /* Bump the source connection read timeout on any activity */
+ if (Comm::IsConnOpen(from.conn)) {
+ AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
+ CommTimeoutCbPtrFun(tunnelTimeout, this));
+ commSetConnTimeout(from.conn, Config.Timeout.read, timeoutCall);
+ }
- if (len < 0 || errcode)
+ if (errcode)
from.error (xerrno);
- else if (len == 0 || fd_closed(to.fd())) {
- comm_close(from.fd());
- /* Only close the remote end if we've finished queueing data to it */
+ else if (len == 0 || !Comm::IsConnOpen(to.conn)) {
+ from.conn->close();
- if (from.len == 0 && !fd_closed(to.fd()) ) {
- comm_close(to.fd());
+ /* Only close the remote end if we've finished queueing data to it */
+ if (from.len == 0 && Comm::IsConnOpen(to.conn) ) {
+ to.conn->close();
}
} else if (cbdataReferenceValid(this)) {
AsyncCall::Pointer call = commCbCall(5,5, "SomeTunnelWriteHandler",
/* Writes data from the client buffer to the server side */
void
-TunnelStateData::WriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
+TunnelStateData::WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
{
TunnelStateData *tunnelState = (TunnelStateData *)data;
- assert(cbdataReferenceValid(tunnelState));
+ assert (cbdataReferenceValid (tunnelState));
- assert(fd == tunnelState->server.fd());
tunnelState->writeServerDone(buf, len, flag, xerrno);
}
void
TunnelStateData::writeServerDone(char *buf, size_t len, comm_err_t flag, int xerrno)
{
- debugs(26, 3, "tunnelWriteServer: FD " << server.fd() << ", " << len << " bytes written");
+ debugs(26, 3, HERE << server.conn << ", " << len << " bytes written");
- if (flag == COMM_ERR_CLOSING)
- return;
-
/* Error? */
- if (len < 0 || flag != COMM_OK) {
- server.error(xerrno); // may call comm_close
+ if (flag != COMM_OK) {
+ if (flag != COMM_ERR_CLOSING)
+ server.error(xerrno); // may call comm_close
return;
}
/* Writes data from the server buffer to the client side */
void
-TunnelStateData::WriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
+TunnelStateData::WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
{
TunnelStateData *tunnelState = (TunnelStateData *)data;
- assert(cbdataReferenceValid(tunnelState));
+ assert (cbdataReferenceValid (tunnelState));
- assert(fd == tunnelState->client.fd());
tunnelState->writeClientDone(buf, len, flag, xerrno);
}
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;
}
TunnelStateData::copyRead(Connection &from, IOCB *completion)
{
assert(from.len == 0);
- comm_read(from.fd(), from.buf, from.bytesWanted(1, SQUID_TCP_SO_RCVBUF), completion, this);
-}
-
-static void
-tunnelConnectTimeout(int fd, void *data)
-{
- TunnelStateData *tunnelState = (TunnelStateData *)data;
- HttpRequest *request = tunnelState->request;
- ErrorState *err = NULL;
-
- if (tunnelState->servers) {
- if (tunnelState->servers->_peer)
- hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
- tunnelState->servers->_peer->host);
- else if (Config.onoff.log_ip_on_direct)
- hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
- fd_table[tunnelState->server.fd()].ipaddr);
- else
- hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
- tunnelState->host);
- } else
- debugs(26, 1, "tunnelConnectTimeout(): tunnelState->servers is NULL");
-
- err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
-
- *tunnelState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
-
- err->xerrno = ETIMEDOUT;
-
- err->port = tunnelState->port;
-
- err->callback = tunnelErrorComplete;
-
- err->callback_data = tunnelState;
-
- errorSend(tunnelState->client.fd(), err);
- comm_close(fd);
+ AsyncCall::Pointer call = commCbCall(5,4, "SomeTunnelReadHandler",
+ CommIoCbPtrFun(completion, this));
+ comm_read(from.conn, from.buf, from.bytesWanted(1, SQUID_TCP_SO_RCVBUF), call);
}
- * Have been written. Start the blind pump.
+/**
+ * All the pieces we need to write to client and/or server connection
++ * have been written.
++ * - Set the HTTP status for this request.
++ * - Start the blind pump.
+ */
static void
-tunnelConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
+tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
{
TunnelStateData *tunnelState = (TunnelStateData *)data;
if (flag != COMM_OK) {
- tunnelErrorComplete(fd, data, 0);
++ *tunnelState->status_ptr = HTTP_INTERNAL_SERVER_ERROR;
+ tunnelErrorComplete(conn->fd, data, 0);
return;
}
++ *tunnelState->status_ptr = HTTP_OK;
if (cbdataReferenceValid(tunnelState)) {
tunnelState->copyRead(tunnelState->server, TunnelStateData::ReadServer);
tunnelState->copyRead(tunnelState->client, TunnelStateData::ReadClient);
}
}
- * handle the write completion from a proxy request to an upstream proxy
+ /*
++ * handle the write completion from a proxy request to an upstream origin
+ */
static void
-tunnelProxyConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
-{
- TunnelStateData *tunnelState = static_cast<TunnelStateData *>(data);
- debugs(26, 3, HERE << "FD " << fd << " tunnelState=" << tunnelState);
- if (flag == COMM_OK)
- *tunnelState->status_ptr = HTTP_OK;
- else
- *tunnelState->status_ptr = HTTP_INTERNAL_SERVER_ERROR;
- tunnelConnectedWriteDone(fd, buf, size, flag, xerrno, data);
-}
-
-static void
-tunnelConnected(int fd, void *data)
+tunnelConnected(const Comm::ConnectionPointer &server, void *data)
{
TunnelStateData *tunnelState = (TunnelStateData *)data;
- debugs(26, 3, "tunnelConnected: FD " << fd << " tunnelState=" << tunnelState);
- *tunnelState->status_ptr = HTTP_OK;
+ debugs(26, 3, HERE << server << ", tunnelState=" << tunnelState);
- *tunnelState->status_ptr = HTTP_OK;
AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
CommIoCbPtrFun(tunnelConnectedWriteDone, tunnelState));
- Comm::Write(tunnelState->client.fd(), conn_established, strlen(conn_established), call, NULL);
+ Comm::Write(tunnelState->client.conn, conn_established, strlen(conn_established), call, NULL);
}
static void
HttpRequest *request = tunnelState->request;
ErrorState *err = NULL;
- request->recordLookup(dns);
+#if USE_DELAY_POOLS
+ /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
+ if (conn->getPeer() && conn->getPeer()->options.no_delay)
+ tunnelState->server.setDelayId(DelayId());
+#endif
- if (tunnelState->servers->_peer)
- hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
- tunnelState->servers->_peer->host);
+ if (conn != NULL && conn->getPeer())
+ hierarchyNote(&tunnelState->request->hier, conn->peerType, conn->getPeer()->host);
else if (Config.onoff.log_ip_on_direct)
- hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
- fd_table[tunnelState->server.fd()].ipaddr);
+ hierarchyNote(&tunnelState->request->hier, conn->peerType, fd_table[conn->fd].ipaddr);
else
- hierarchyNote(&tunnelState->request->hier, tunnelState->servers->code,
- tunnelState->host);
-
- if (status == COMM_ERR_DNS) {
- debugs(26, 4, "tunnelConnect: Unknown host: " << tunnelState->host);
- err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND, request);
- *tunnelState->status_ptr = HTTP_NOT_FOUND;
- err->dnsError = dns.error;
- err->callback = tunnelErrorComplete;
- err->callback_data = tunnelState;
- errorSend(tunnelState->client.fd(), err);
- } else if (status != COMM_OK) {
- err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
- *tunnelState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
- err->xerrno = xerrno;
- err->port = tunnelState->port;
- err->callback = tunnelErrorComplete;
- err->callback_data = tunnelState;
- errorSend(tunnelState->client.fd(), err);
- } else {
- if (tunnelState->servers->_peer && !tunnelState->servers->_peer->options.originserver)
- tunnelProxyConnected(tunnelState->server.fd(), tunnelState);
- else {
- tunnelConnected(tunnelState->server.fd(), tunnelState);
+ hierarchyNote(&tunnelState->request->hier, conn->peerType, tunnelState->getHost());
+
- // TODO: merge this into hierarchyNote with a conn parameter instead of peerType
- request->hier.peer_local_port = conn->local.GetPort(); // for %<lp logging
-
+ if (status != COMM_OK) {
+ /* At this point only the TCP handshake has failed. no data has been passed.
+ * we are allowed to re-try the TCP-level connection to alternate IPs for CONNECT.
+ */
+ tunnelState->serverDestinations.shift();
+ if (status != COMM_TIMEOUT && tunnelState->serverDestinations.size() > 0) {
+ /* Try another IP of this destination host */
+ AsyncCall::Pointer call = commCbCall(26,3, "tunnelConnectDone", CommConnectCbPtrFun(tunnelConnectDone, tunnelState));
+ Comm::ConnOpener *cs = new Comm::ConnOpener(tunnelState->serverDestinations[0], call, Config.Timeout.connect);
+ cs->setHost(tunnelState->url);
+ AsyncJob::Start(cs);
+ } else {
+ err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
+ *tunnelState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
+ err->xerrno = xerrno;
+ // on timeout is this still: err->xerrno = ETIMEDOUT;
+ err->port = conn->remote.GetPort();
+ err->callback = tunnelErrorComplete;
+ err->callback_data = tunnelState;
+ errorSend(tunnelState->client.conn, err);
}
- tunnelState->request->flags.proxying = 1;
+ return;
+ }
+
+ tunnelState->server.conn = conn;
+ request->peer_host = conn->getPeer() ? conn->getPeer()->host : NULL;
+ comm_add_close_handler(conn->fd, tunnelServerClosed, tunnelState);
+
+ if (conn->getPeer()) {
+ tunnelState->request->peer_login = conn->getPeer()->login;
++ tunnelState->request->flags.proxying = (conn->getPeer()->options.originserver?0:1);
+ } else {
+ tunnelState->request->peer_login = NULL;
+ tunnelState->request->flags.proxying = 0;
+ }
- if (conn->getPeer())
- commSetTimeout(tunnelState->server.fd(),
- Config.Timeout.read,
- tunnelTimeout,
- tunnelState);
++ if (tunnelState->request->flags.proxying)
+ tunnelRelayConnectRequest(conn, tunnelState);
+ else {
+ tunnelConnected(conn, tunnelState);
}
+
+ AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
+ CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
+ commSetConnTimeout(conn, Config.Timeout.read, timeoutCall);
}
extern tos_t GetTosToServer(HttpRequest * request);
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 */
#if USE_WCCP
#include "squid.h"
-
#include "comm.h"
+#include "comm/Connection.h"
#include "comm/Loops.h"
#include "event.h"
}
void
-WhoisState::readReply (int fd, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno)
+WhoisState::readReply(const Comm::ConnectionPointer &conn, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno)
{
- int do_next_read = 0;
-
/* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
-
- if (flag == COMM_ERR_CLOSING) {
+ if (flag == COMM_ERR_CLOSING)
return;
- }
aBuffer[aBufferLength] = '\0';
- debugs(75, 3, "whoisReadReply: FD " << fd << " read " << aBufferLength << " bytes");
+ debugs(75, 3, HERE << conn << " read " << aBufferLength << " bytes");
debugs(75, 5, "{" << aBuffer << "}");
- if (flag == COMM_OK && aBufferLength > 0) {
- if (!dataWritten)
- setReplyToOK(entry);
-
- kb_incr(&statCounter.server.all.kbytes_in, aBufferLength);
-
- kb_incr(&statCounter.server.http.kbytes_in, aBufferLength);
-
- /* No range support, we always grab it all */
- dataWritten = true;
-
- entry->append(aBuffer, aBufferLength);
-
- entry->flush();
-
- do_next_read = 1;
- } else if (flag != COMM_OK || aBufferLength < 0) {
+ if (flag != COMM_OK) {
- debugs(50, 2, "whoisReadReply: FD " << fd << ": read failure: " << xstrerror() << ".");
+ debugs(50, 2, HERE << conn << ": read failure: " << xstrerror() << ".");
if (ignoreErrno(errno)) {
- do_next_read = 1;
- comm_read(fd, aBuffer, BUFSIZ, whoisReadReply, this);
++ AsyncCall::Pointer call = commCbCall(5,4, "whoisReadReply",
++ CommIoCbPtrFun(whoisReadReply, this));
++ comm_read(conn, aBuffer, BUFSIZ, call);
} else {
ErrorState *err;
err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, fwd->request);
err->xerrno = errno;
fwd->fail(err);
- comm_close(fd);
+ conn->close();
- do_next_read = 0;
}
- } else {
- entry->timestampsSet();
- entry->flush();
+ return;
+ }
- if (!EBIT_TEST(entry->flags, RELEASE_REQUEST))
- entry->setPublicKey();
+ if (aBufferLength > 0) {
+ if (!dataWritten)
+ setReplyToOK(entry);
- fwd->complete();
- debugs(75, 3, "whoisReadReply: Done: " << entry->url() );
- conn->close();
- do_next_read = 0;
- }
+ kb_incr(&statCounter.server.all.kbytes_in, aBufferLength);
+ kb_incr(&statCounter.server.http.kbytes_in, aBufferLength);
+
+ /* No range support, we always grab it all */
+ dataWritten = true;
+ entry->append(aBuffer, aBufferLength);
+ entry->flush();
- if (do_next_read) {
- comm_read(fd, aBuffer, BUFSIZ, whoisReadReply, this);
+ AsyncCall::Pointer call = commCbCall(5,4, "whoisReadReply",
+ CommIoCbPtrFun(whoisReadReply, this));
+ comm_read(conn, aBuffer, BUFSIZ, call);
+ return;
}
- comm_close(fd);
+
+ /* no bytes read. stop reading */
+ entry->timestampsSet();
+ entry->flush();
+
+ if (!EBIT_TEST(entry->flags, RELEASE_REQUEST))
+ entry->setPublicKey();
+
+ fwd->complete();
+ debugs(75, 3, "whoisReadReply: Done: " << entry->url());
++ conn->close();
}
static void