<tag>cpu_affinity_map</tag>
<p>New setting for SMP support to map Squid processes onto specific CPU cores.
- This directive applies to all hosts, extending the number of connection attempts to each IP address.
+ <tag>connect_retries</tag>
+ <p>Replacement for <em>maximum_single_addr_tries</em>, but instead of only applying to hosts with single addresses.
++ This directive applies to all hosts, extending the number of connection attempts to each IP address. =======
++
+ <tag>dns_packet_max</tag>
+ <p>New setting to configure maximum number of bytes packet size to advertise via EDNS.
+ Set to "none" (the initial default) to disable EDNS large packet support.
<tag>else</tag>
<p>Part of conditional SMP support syntax. see <em>if</em>
#ifndef SQUID_CACHEMANAGER_H
#define SQUID_CACHEMANAGER_H
- #include "squid.h"
- #include "Array.h"
+#include "comm/forward.h"
+ #include "mgr/Action.h"
+ #include "mgr/ActionProfile.h"
+ #include "mgr/Command.h"
+ #include "mgr/forward.h"
+ #include <vector>
/**
\defgroup CacheManagerAPI Cache Manager API
*/
class CacheManager
{
-
public:
- /* the holy trinity - assignment, copy cons, destructor */
- /* unimplemented - prevents bugs from synthetic */
- CacheManager & operator = (CacheManager &);
- /* unimplemented - prevents bugs from synthetic */
- CacheManager(CacheManager const &);
- /* inline so that we dont need to link in cachemgr.cc at all in tests */
- virtual ~CacheManager() {}
-
- void registerAction(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic);
- void registerAction(CacheManagerAction *anAction);
- CacheManagerAction * findAction(char const * action);
+ typedef std::vector<Mgr::ActionProfilePointer> Menu;
+
+ void registerProfile(char const * action, char const * desc,
+ OBJH * handler,
+ int pw_req_flag, int atomic);
+ void registerProfile(char const * action, char const * desc,
+ Mgr::ClassActionCreationHandler *handler,
+ int pw_req_flag, int atomic);
+ Mgr::ActionProfilePointer findAction(char const * action) const;
+ Mgr::Action::Pointer createNamedAction(const char *actionName);
+ Mgr::Action::Pointer createRequestedAction(const Mgr::ActionParams &);
+ const Menu& menu() const { return menu_; }
- void Start(int fd, HttpRequest * request, StoreEntry * entry);
+ void Start(const Comm::ConnectionPointer &client, HttpRequest * request, StoreEntry * entry);
static CacheManager* GetInstance();
- const char *ActionProtection(const CacheManagerAction * at);
+ const char *ActionProtection(const Mgr::ActionProfilePointer &profile);
protected:
- // command classes. They are private to the cachemanager, they
- // may require access to local data, plus we avoid polluting
- // the namespace more than needed.
- class ShutdownAction : public CacheManagerAction
- {
- public:
- virtual void run (StoreEntry *sentry);
- ShutdownAction();
- };
- class ReconfigureAction : public CacheManagerAction
- {
- public:
- virtual void run (StoreEntry *sentry);
- ReconfigureAction();
- };
- class RotateAction : public CacheManagerAction
- {
- public:
- virtual void run (StoreEntry *sentry);
- RotateAction();
- };
- class OfflineToggleAction : public CacheManagerAction
- {
- public:
- virtual void run (StoreEntry *sentry);
- OfflineToggleAction();
- };
- class MenuAction : public CacheManagerAction
- {
- private:
- //needs to reference the cachemgr in order to get to ActionsList
- CacheManager *cmgr;
- public:
- virtual void run (StoreEntry *sentry);
- MenuAction(CacheManager *);
-
- };
+ CacheManager() {} ///< use Instance() instead
- /// \ingroup CacheManagerInternal
- typedef struct {
- StoreEntry *entry;
- char *action;
- char *user_name;
- char *passwd;
- } cachemgrStateData;
-
-
- CacheManager();
- cachemgrStateData* ParseUrl(const char *url);
- void ParseHeaders(cachemgrStateData * mgr, const HttpRequest * request);
- int CheckPassword(cachemgrStateData * mgr);
+ Mgr::CommandPointer ParseUrl(const char *url);
+ void ParseHeaders(const HttpRequest * request, Mgr::ActionParams ¶ms);
+ int CheckPassword(const Mgr::Command &cmd);
char *PasswdGet(cachemgr_passwd *, const char *);
- // \ingroup CacheManagerInternal
- typedef Vector<CacheManagerAction *> CacheManagerActionList;
- CacheManagerActionList ActionsList;
+ void registerProfile(const Mgr::ActionProfilePointer &profile);
+ Menu menu_;
private:
static CacheManager* instance;
#if ICAP_CLIENT
#include "adaptation/icap/icap_log.h"
#endif
-#include "acl/FilledChecklist.h"
+#include "auth/UserRequest.h"
+#include "DnsLookupDetails.h"
+ #include "err_detail_type.h"
+#include "HttpRequest.h"
+#include "HttpHeaderRange.h"
+#include "MemBuf.h"
+#include "Store.h"
HttpRequest::HttpRequest() : HttpMsg(hoRequest)
{
#include "adaptation/Initiator.h"
#include "auth/UserRequest.h"
#include "base/TextException.h"
+ #include "base64.h"
#include "ChunkedCodingParser.h"
#include "comm.h"
+#include "comm/Connection.h"
#include "HttpMsg.h"
#include "HttpRequest.h"
#include "HttpReply.h"
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
+
#include "config.h"
+ #include "base/TextException.h"
#include "CacheManager.h"
+#include "comm/Connection.h"
+ #include "Debug.h"
#include "errorpage.h"
+ #include "fde.h"
#include "HttpReply.h"
#include "HttpRequest.h"
- #include "Store.h"
- #include "fde.h"
+ #include "mgr/ActionCreator.h"
+ #include "mgr/Action.h"
+ #include "mgr/ActionProfile.h"
+ #include "mgr/BasicActions.h"
+ #include "mgr/Command.h"
+ #include "mgr/Forwarder.h"
+ #include "mgr/FunAction.h"
-#include "protos.h" /* rotate_logs() */
++/* for rotate_logs() */
++#include "protos.h"
#include "SquidTime.h"
+ #include "Store.h"
#include "wordlist.h"
- #include "Debug.h"
+ #include <algorithm>
- // for rotate_logs()
- #include "protos.h"
/// \ingroup CacheManagerInternal
#define MGR_PASSWD_SZ 128
* Implemented via CacheManagerActionLegacy.
*/
void
- CacheManager::registerAction(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic)
+ CacheManager::registerProfile(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic)
{
- debugs(16, 3, "CacheManager::registerAction: registering legacy " << action);
- registerAction(new CacheManagerActionLegacy(action,desc,pw_req_flag,atomic,handler));
+ debugs(16, 3, HERE << "registering legacy " << action);
+ const Mgr::ActionProfile::Pointer profile = new Mgr::ActionProfile(action,
+ desc, pw_req_flag, atomic, new Mgr::FunActionCreator(handler));
+ registerProfile(profile);
}
- * Registers a C++-style action, via a poiner to a subclass of
+/**
+ * \ingroup CacheManagerAPI
++ * Registers a C++-style action, via a pointer to a subclass of
+ * a CacheManagerAction object, whose run() method will be invoked when
+ * CacheManager identifies that the user has requested the action.
+ */
void
- CacheManager::registerAction(CacheManagerAction *anAction)
+ CacheManager::registerProfile(char const * action, char const * desc,
+ ClassActionCreator::Handler *handler,
+ int pw_req_flag, int atomic)
{
- char *action = anAction->action;
- if (findAction(action) != NULL) {
- debugs(16, 2, "CacheManager::registerAction: Duplicate '" << action << "'. Skipping.");
- return;
- }
-
- assert (strstr (" ", action) == NULL);
-
- ActionsList += anAction;
-
- debugs(16, 3, "CacheManager::registerAction: registered " << action);
+ const Mgr::ActionProfile::Pointer profile = new Mgr::ActionProfile(action,
+ desc, pw_req_flag, atomic, new ClassActionCreator(handler));
+ registerProfile(profile);
}
-
/**
\ingroup CacheManagerInternal
* Locates an action in the actions registry ActionsList.
* all needed internal work and renders the response.
*/
void
-CacheManager::Start(int fd, HttpRequest * request, StoreEntry * entry)
+CacheManager::Start(const Comm::ConnectionPointer &client, HttpRequest * request, StoreEntry * entry)
{
- cachemgrStateData *mgr = NULL;
ErrorState *err = NULL;
- CacheManagerAction *a;
debugs(16, 3, "CacheManager::Start: '" << entry->url() << "'" );
- if ((mgr = ParseUrl(entry->url())) == NULL) {
+ Mgr::Command::Pointer cmd = ParseUrl(entry->url());
+ if (!cmd) {
err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND, request);
err->url = xstrdup(entry->url());
errorAppendEntry(entry, err);
return;
}
- mgr->entry = entry;
+ const char *actionName = cmd->profile->name;
- entry->lock();
entry->expires = squid_curtime;
- debugs(16, 5, "CacheManager: " << client << " requesting '" << mgr->action << "'");
- debugs(16, 5, "CacheManager: " << fd_table[fd].ipaddr << " requesting '" << actionName << "'");
++ debugs(16, 5, "CacheManager: " << client << " requesting '" << actionName << "'");
/* get additional info from request headers */
- ParseHeaders(mgr, request);
+ ParseHeaders(request, cmd->params);
+
+ const char *userName = cmd->params.userName.size() ?
+ cmd->params.userName.termedBuf() : "unknown";
/* Check password */
errState = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED, request);
/* warn if user specified incorrect password */
- if (mgr->passwd)
+ if (cmd->params.password.size()) {
debugs(16, DBG_IMPORTANT, "CacheManager: " <<
- (mgr->user_name ? mgr->user_name : "<unknown>") << "@" <<
+ userName << "@" <<
- fd_table[fd].ipaddr << ": incorrect password for '" <<
+ client << ": incorrect password for '" <<
- mgr->action << "'" );
- else
+ actionName << "'" );
+ } else {
debugs(16, DBG_IMPORTANT, "CacheManager: " <<
- (mgr->user_name ? mgr->user_name : "<unknown>") << "@" <<
+ userName << "@" <<
- fd_table[fd].ipaddr << ": password needed for '" <<
+ client << ": password needed for '" <<
- mgr->action << "'");
+ actionName << "'" );
+ }
rep = errState->BuildHttpReply();
}
debugs(16, 2, "CacheManager: " <<
- (mgr->user_name ? mgr->user_name : "<unknown>") << "@" <<
+ userName << "@" <<
- fd_table[fd].ipaddr << " requesting '" <<
+ client << " requesting '" <<
- mgr->action << "'" );
- /* retrieve object requested */
- a = findAction(mgr->action);
- assert(a != NULL);
+ actionName << "'" );
- entry->buffer();
-
- {
- HttpReply *rep = new HttpReply;
- rep->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime);
- entry->replaceHttpReply(rep);
+ if (UsingSmp() && IamWorkerProcess()) {
+ AsyncJob::Start(new Mgr::Forwarder(fd, cmd->params, request, entry));
+ return;
}
- a->run(entry);
-
- entry->flush();
-
- if (a->flags.atomic)
- entry->complete();
-
- StateFree(mgr);
+ Mgr::Action::Pointer action = cmd->profile->creator->create(cmd);
+ Must(action != NULL);
+ action->run(entry, true);
}
- /// \ingroup CacheManagerInternal
- void CacheManager::ShutdownAction::run(StoreEntry *sentry)
- {
- debugs(16, DBG_CRITICAL, "Shutdown by Cache Manager command.");
- shut_down(0);
- }
- /// \ingroup CacheManagerInternal
- CacheManager::ShutdownAction::ShutdownAction() : CacheManagerAction("shutdown","Shut Down the Squid Process", 1, 1) { }
-
- /// \ingroup CacheManagerInternal
- void
- CacheManager::ReconfigureAction::run(StoreEntry * sentry)
- {
- debugs(16, DBG_IMPORTANT, "Reconfigure by Cache Manager command.");
- storeAppendPrintf(sentry, "Reconfiguring Squid Process ....");
- reconfigure(SIGHUP);
- }
- /// \ingroup CacheManagerInternal
- CacheManager::ReconfigureAction::ReconfigureAction() : CacheManagerAction("reconfigure","Reconfigure Squid", 1, 1) { }
-
- /// \ingroup CacheManagerInternal
- void
- CacheManager::RotateAction::run(StoreEntry * sentry)
- {
- debugs(16, DBG_IMPORTANT, "Rotate Logs by Cache Manager command.");
- storeAppendPrintf(sentry, "Rotating Squid Process Logs ....");
- #ifdef _SQUID_LINUX_THREADS_
- rotate_logs(SIGQUIT);
- #else
- rotate_logs(SIGUSR1);
- #endif
- }
- /// \ingroup CacheManagerInternal
- CacheManager::RotateAction::RotateAction() : CacheManagerAction("rotate","Rotate Squid Logs", 1, 1) { }
-
- /// \ingroup CacheManagerInternal
- void
- CacheManager::OfflineToggleAction::run(StoreEntry * sentry)
- {
- Config.onoff.offline = !Config.onoff.offline;
- debugs(16, DBG_IMPORTANT, "offline_mode now " << (Config.onoff.offline ? "ON" : "OFF") << " by Cache Manager request.");
-
- storeAppendPrintf(sentry, "offline_mode is now %s\n",
- Config.onoff.offline ? "ON" : "OFF");
- }
- /// \ingroup CacheManagerInternal
- CacheManager::OfflineToggleAction::OfflineToggleAction() : CacheManagerAction ("offline_toggle", "Toggle offline_mode setting", 1, 1) { }
-
/*
\ingroup CacheManagerInternal
* Renders the protection level text for an action.
/* 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()->clientConn->local.ToHostname(ipbuf,MAX_IPSTRLEN);
snprintf(http->uri, url_sz, "%s://%s:%d%s",
http->getConn()->port->protocol,
- http->getConn()->clientConn->local.NtoA(ntoabuf,MAX_IPSTRLEN),
- http->getConn()->clientConn->local.GetPort(), url);
- ipbuf, http->getConn()->me.GetPort(), url);
++ ipbuf, http->getConn()->clientConn->local.GetPort(), url);
debugs(33, 5, "ACCEL VPORT REWRITE: '" << http->uri << "'");
} else if (vport > 0) {
/* Put the local socket IP address as the hostname, but static port */
int url_sz = strlen(url) + 32 + Config.appendDomainLen;
http->uri = (char *)xcalloc(url_sz, 1);
- http->getConn()->me.ToHostname(ipbuf,MAX_IPSTRLEN);
++ http->getConn()->clientConn->local.ToHostname(ipbuf,MAX_IPSTRLEN);
snprintf(http->uri, url_sz, "%s://%s:%d%s",
http->getConn()->port->protocol,
- http->getConn()->clientConn->local.NtoA(ntoabuf,MAX_IPSTRLEN),
- vport, url);
+ ipbuf, vport, url);
debugs(33, 5, "ACCEL VPORT REWRITE: '" << http->uri << "'");
}
}
/* 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()->clientConn->local.ToHostname(ipbuf,MAX_IPSTRLEN),
snprintf(http->uri, url_sz, "%s://%s:%d%s",
http->getConn()->port->protocol,
- http->getConn()->clientConn->local.NtoA(ntoabuf,MAX_IPSTRLEN),
- http->getConn()->clientConn->local.GetPort(), url);
- ipbuf, http->getConn()->me.GetPort(), url);
++ ipbuf, http->getConn()->clientConn->local.GetPort(), url);
debugs(33, 5, "TRANSPARENT REWRITE: '" << http->uri << "'");
}
}
request->client_eui64 = conn->peer_eui64;
#endif
#if FOLLOW_X_FORWARDED_FOR
- request->indirect_client_addr = conn->peer;
+ request->indirect_client_addr = conn->clientConn->remote;
#endif /* FOLLOW_X_FORWARDED_FOR */
- request->my_addr = conn->me;
+ request->my_addr = conn->clientConn->local;
+ request->myportname = conn->port->name;
request->http_ver = http_ver;
if (request->header.chunked()) {
connState->readSomeData();
- clientdbEstablished(details->peer, 1);
+ clientdbEstablished(details->remote, 1);
+ #if DELAY_POOLS
+ fd_table[newfd].clientInfo = NULL;
+
+ if (Config.onoff.client_db) {
+ /* it was said several times that client write limiter does not work if client_db is disabled */
+
+ ClientDelayPools& pools(Config.ClientDelay.pools);
+ for (unsigned int pool = 0; pool < pools.size(); pool++) {
+
+ /* pools require explicit 'allow' to assign a client into them */
+ if (!pools[pool].access)
+ continue; // warned in ClientDelayConfig::Finalize()
+
+ ACLFilledChecklist ch(pools[pool].access, NULL, NULL);
+
+ // 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;
+
+ 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);
+ assert(cli);
+
+ /* put client info in FDE */
+ fd_table[newfd].clientInfo = cli;
+
+ /* setup write limiter for this request */
+ const double burst = floor(0.5 +
+ (pools[pool].highwatermark * Config.ClientDelay.initial)/100.0);
+ cli->setWriteLimiter(pools[pool].rate, burst, pools[pool].highwatermark);
+ break;
+ }
+ }
+ }
+ #endif
incoming_sockets_accepted++;
}
static void commStopHalfClosedMonitor(int fd);
static IOCB commHalfClosedReader;
-static void comm_init_opened(int new_socket, Ip::Address &addr, tos_t tos, nfmark_t nfmark, const char *note, struct addrinfo *AI);
+static void comm_init_opened(const Comm::ConnectionPointer &conn, tos_t tos, nfmark_t nfmark, const char *note, struct addrinfo *AI);
static int comm_apply_flags(int new_socket, Ip::Address &addr, int flags, struct addrinfo *AI);
+ #if DELAY_POOLS
+ CBDATA_CLASS_INIT(CommQuotaQueue);
+
+ static void commHandleWriteHelper(void * data);
+ #endif
+
+ static void commSelectOrQueueWrite(const int fd);
struct comm_io_callback_t {
iocb_type type;
}
void
-comm_write(int fd, const char *buf, int size, AsyncCall::Pointer &callback, FREE * free_func)
+comm_write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE * free_func)
{
- debugs(5, 5, "comm_write: FD " << fd << ": sz " << size << ": asynCall " << callback);
+ debugs(5, 5, HERE << conn << ": sz " << size << ": asynCall " << callback);
/* Make sure we are open, not closing, and not writing */
- assert(isOpen(fd));
- assert(!fd_table[fd].closing());
- comm_io_callback_t *ccb = COMMIO_FD_WRITECB(fd);
+ assert(Comm::IsConnOpen(conn));
+ assert(!fd_table[conn->fd].closing());
+ comm_io_callback_t *ccb = COMMIO_FD_WRITECB(conn->fd);
assert(!ccb->active());
- fd_table[fd].writeStart = squid_curtime;
+ fd_table[conn->fd].writeStart = squid_curtime;
/* Queue the write */
- commio_set_callback(fd, IOCB_WRITE, ccb, callback,
+ commio_set_callback(conn->fd, IOCB_WRITE, ccb, callback,
(char *)buf, free_func, size);
- commSetSelect(conn->fd, COMM_SELECT_WRITE, commHandleWrite, ccb, 0);
-
- commSelectOrQueueWrite(fd);
++ commSelectOrQueueWrite(conn->fd);
+ }
+
+ // called when fd needs to write but may need to wait in line for its quota
+ static void
+ commSelectOrQueueWrite(const int fd)
+ {
+ comm_io_callback_t *ccb = COMMIO_FD_WRITECB(fd);
+
+ #if DELAY_POOLS
+ // stand in line if there is one
+ if (ClientInfo *clientInfo = fd_table[fd].clientInfo) {
+ if (clientInfo->writeLimitingActive) {
+ ccb->quotaQueueReserv = clientInfo->quotaEnqueue(fd);
+ clientInfo->kickQuotaQueue();
+ return;
+ }
+ }
+ #endif
+
+ commSetSelect(fd, COMM_SELECT_WRITE, commHandleWrite, ccb, 0);
++>>>>>>> MERGE-SOURCE
}
#define COMM_SELECT_READ (0x1)
#define COMM_SELECT_WRITE (0x2)
- #define safe_free(x) if (x) { xxfree(x); x = NULL; }
++/*
+ #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)
*
*/
-#include "config.h"
#include "squid.h"
- #include "CacheManager.h"
-#include "event.h"
-#include "SquidTime.h"
-#include "Store.h"
++#include "base/InstanceId.h"
+#include "comm/Connection.h"
+#include "comm/ConnOpener.h"
#include "comm.h"
+#include "event.h"
#include "fde.h"
#include "ip/tools.h"
#include "MemBuf.h"
+#include "SquidTime.h"
+#include "Store.h"
+ #include "mgr/Registration.h"
+ #include "util.h"
#include "wordlist.h"
-#include "base/InstanceId.h"
#if HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
static EVH idnsCheckQueue;
static void idnsTickleQueue(void);
static void idnsRcodeCount(int, int);
+static void idnsVCClosed(int fd, void *data);
+ static unsigned short idnsQueryID(void);
static void
idnsAddNameserver(const char *buf)
}
assert(vc->ns < nns);
- debugs(78, 3, "idnsReadVC: FD " << fd << ": received " <<
- (int) vc->msg->contentSize() << " bytes via tcp from " <<
- nameservers[vc->ns].S << ".");
+ debugs(78, 3, HERE << conn << ": received " << vc->msg->contentSize() << " bytes via TCP from " << nameservers[vc->ns].S << ".");
- idnsGrokReply(vc->msg->buf, vc->msg->contentSize());
+ idnsGrokReply(vc->msg->buf, vc->msg->contentSize(), vc->ns);
vc->msg->clean();
- comm_read(fd, (char *)&vc->msglen, 2 , idnsReadVCHeader, vc);
+ comm_read(conn, (char *)&vc->msglen, 2 , idnsReadVCHeader, vc);
}
static void
*/
#include "config.h"
-#include "errorpage.h"
#include "auth/UserRequest.h"
-#include "SquidTime.h"
-#include "Store.h"
+#include "comm/Connection.h"
++#include "err_detail_type.h"
+#include "errorpage.h"
+#include "fde.h"
+ #include "html_quote.h"
#include "HttpReply.h"
#include "HttpRequest.h"
-#include "MemObject.h"
-#include "fde.h"
#include "MemBuf.h"
+#include "MemObject.h"
#include "rfc1738.h"
+#include "SquidTime.h"
+#include "Store.h"
#include "URLScheme.h"
#include "wordlist.h"
-#include "err_detail_type.h"
/**
\defgroup ErrorPageInternal Error Page Internals
#include "squid.h"
-#include "forward.h"
#include "acl/FilledChecklist.h"
#include "acl/Gadgets.h"
--#include "CacheManager.h"
+#include "comm/Connection.h"
+#include "comm/ConnOpener.h"
+#include "CommCalls.h"
#include "event.h"
#include "errorpage.h"
#include "fde.h"
#include "Store.h"
#include "icmp/net_db.h"
#include "ip/Intercept.h"
-
+ #include "ip/tools.h"
+ #include "mgr/Registration.h"
-static PSC fwdStartCompleteWrapper;
+static PSC fwdPeerSelectionCompleteWrapper;
static PF fwdServerClosedWrapper;
#if USE_SSL
static PF fwdNegotiateSSLWrapper;
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);
}
-
- tos_t tos = GetTosToServer(request);
-
#if SO_MARK
- if (Ip::Qos::TheConfig.isAclNfmarkActive()) {
- serverDestinations[0]->nfmark = GetNfmarkToServer(request);
- }
- nfmark_t mark = GetNfmarkToServer(request);
++ serverDestinations[0]->nfmark = GetNfmarkToServer(request);
+ debugs(17, 3, "fwdConnectStart: got outgoing addr " << outgoing << ", tos " << int(tos)
- << ", netfilter mark " << mark);
++ << ", netfilter mark " << serverDestinations[0]->nfmark);
+ #else
- nfmark_t mark = 0;
++ serverDestinations[0]->nfmark = 0;
+ debugs(17, 3, "fwdConnectStart: got outgoing addr " << outgoing << ", tos " << int(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++;
-
- request->hier.peer_local_port = comm_local_port(fd);
-
- /*
- * 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
+ AsyncCall::Pointer call = commCbCall(17,3, "fwdConnectDoneWrapper", CommConnectCbPtrFun(fwdConnectDoneWrapper, this));
+ Comm::ConnOpener *cs = new Comm::ConnOpener(serverDestinations[0], call, ctimeout);
+ cs->setHost(host);
+ AsyncJob::Start(cs);
}
void
#include "squid.h"
#include "cbdata.h"
+#include "DnsLookupDetails.h"
#include "event.h"
- #include "CacheManager.h"
+ #include "mgr/Registration.h"
#include "SquidTime.h"
#include "Store.h"
#include "wordlist.h"
#include "auth/UserRequest.h"
#include "base/AsyncJobCalls.h"
#include "base/TextException.h"
+ #include "base64.h"
+#include "comm/Connection.h"
#if DELAY_POOLS
#include "DelayPools.h"
#endif
icpConnectionsOpen(void)
{
uint16_t port;
- // Ip::Address addr;
- Ip::Address addr;
if ((port = Config.Port.icp) <= 0)
return;
fatal("ICP port cannot be opened.");
}
/* split-stack for now requires default IPv4-only ICP */
- if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && addr.IsAnyAddr()) {
- addr.SetIPv4();
+ if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpOutgoingConn->local.IsAnyAddr()) {
+ icpOutgoingConn->local.SetIPv4();
}
- theOutIcpConnection = comm_open_listener(SOCK_DGRAM,
- IPPROTO_UDP,
- addr,
- COMM_NONBLOCKING,
- "ICP Port");
+ enter_suid();
+ comm_open_listener(SOCK_DGRAM, IPPROTO_UDP, icpOutgoingConn, "Outgoing ICP Port");
leave_suid();
- if (theOutIcpConnection < 0)
+ if (!Comm::IsConnOpen(icpOutgoingConn))
fatal("Cannot open Outgoing ICP Port");
- commSetSelect(theOutIcpConnection,
- COMM_SELECT_READ,
- icpHandleUdp,
- NULL,
- 0);
-
- debugs(12, 1, "Outgoing ICP messages on port " << addr.GetPort() << ", FD " << theOutIcpConnection << ".");
+ debugs(12, DBG_CRITICAL, "Sending ICP messages from " << icpOutgoingConn->local);
+ commSetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
+ fd_note(theOutIcpConnection, "Outgoing ICP socket");
+ icpGetOutgoingIpAddress();
}
+ }
- // Ensure that we have the IP address(es) to use for Host ID.
- // The outgoing address is used as 'private' host ID used only on packets we send
++// Ensure that we have the IP address(es) to use for Host ID.
++// The outgoing address is used as 'private' host ID used only on packets we send
+ static void
+ icpGetOutgoingIpAddress()
+ {
struct addrinfo *xai = NULL;
- theOutICPAddr.InitAddrInfo(xai);
-
- if (getsockname(theOutIcpConnection, xai->ai_addr, &xai->ai_addrlen) < 0)
- debugs(50, 1, "theOutIcpConnection FD " << theOutIcpConnection << ": getsockname: " << xstrerror());
+ theOutICPAddr.SetEmpty();
+ theIcpPrivateHostID.InitAddrInfo(xai);
+ if (getsockname(icpOutgoingConn->fd, xai->ai_addr, &xai->ai_addrlen) < 0)
+ debugs(50, DBG_IMPORTANT, "ERROR: Unable to identify ICP host ID to use for " << icpOutgoingConn
+ << ": getsockname: " << xstrerror());
else
- theOutICPAddr = *xai;
-
- theOutICPAddr.FreeAddrInfo(xai);
+ theIcpPrivateHostID = *xai;
+ theIcpPrivateHostID.FreeAddrInfo(xai);
}
static void
-icpIncomingConnectionOpened(int fd, int errNo, Ip::Address& addr)
+icpIncomingConnectionOpened(int errNo)
{
- theInIcpConnection = fd;
-
- if (theInIcpConnection < 0)
+ if (!Comm::IsConnOpen(icpIncomingConn))
fatal("Cannot open ICP Port");
- commSetSelect(theInIcpConnection,
- COMM_SELECT_READ,
- icpHandleUdp,
- NULL,
- 0);
+ commSetSelect(icpIncomingConn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
for (const wordlist *s = Config.mcast_group_list; s; s = s->next)
- ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL);
+ ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL); // XXX: pass the icpIncomingConn for mcastJoinGroups usage.
- debugs(12, 1, "Accepting ICP messages at " << addr << ", FD " << theInIcpConnection << ".");
+ debugs(12, DBG_IMPORTANT, "Accepting ICP messages on " << icpIncomingConn->local);
- fd_note(theInIcpConnection, "Incoming ICP socket");
+ fd_note(icpIncomingConn->fd, "Incoming ICP port");
if (Config.Addrs.udp_outgoing.IsNoAddr()) {
- theOutIcpConnection = theInIcpConnection;
+ icpOutgoingConn = icpIncomingConn;
+ debugs(12, DBG_IMPORTANT, "Sending ICP messages from " << icpOutgoingConn->local);
+ icpGetOutgoingIpAddress();
}
+
+ // Ensure that we have the IP address(es) to use for Host ID.
+ // The listening address is used as 'public' host ID which can be used to contact us
+ struct addrinfo *xai = NULL;
+ theIcpPublicHostID.InitAddrInfo(xai); // reset xai
+ if (getsockname(icpIncomingConn->fd, xai->ai_addr, &xai->ai_addrlen) < 0)
+ debugs(50, DBG_IMPORTANT, "ERROR: Unable to identify ICP host ID to use for " << icpIncomingConn
+ << ": getsockname: " << xstrerror());
+ else
+ theIcpPublicHostID = *xai;
+ theIcpPublicHostID.FreeAddrInfo(xai);
}
/**
/* Query the conntrack table using the data previously set */
int x = nfct_query(h, NFCT_Q_GET, ct);
if (x == -1) {
- debugs(17, 2, "QOS: Failed to retrieve connection mark: (" << x << ") " << xstrerror(errno)
+ debugs(17, 2, "QOS: Failed to retrieve connection mark: (" << x << ") " << strerror(errno)
- << " (Destination " << servFde->ipaddr << ":" << servFde->remote_port
- << ", source " << serv_fde_local_conn << ")" );
+ << " (Destination " << server->remote << ", source " << server->local << ")" );
}
-
nfct_close(h);
} else {
debugs(17, 2, "QOS: Failed to open conntrack handle for upstream netfilter mark retrieval.");
#include "config.h"
-#include "CacheManager.h"
+#include "base/Subscription.h"
+ #include "base/TextException.h"
#include "comm.h"
+#include "comm/Connection.h"
#include "ipc/Coordinator.h"
#include "ipc/FdNotes.h"
#include "ipc/SharedListen.h"
SendMessage(MakeAddr(strandAddrPfx, request.requestorId), message);
}
-int
+ void
+ Ipc::Coordinator::handleCacheMgrRequest(const Mgr::Request& request)
+ {
+ debugs(54, 4, HERE);
+
+ // Let the strand know that we are now responsible for handling the request
+ Mgr::Response response(request.requestId);
+ TypedMsgHdr message;
+ response.pack(message);
+ SendMessage(MakeAddr(strandAddrPfx, request.requestorId), message);
+
+ Mgr::Action::Pointer action =
+ CacheManager::GetInstance()->createRequestedAction(request.params);
+ AsyncJob::Start(new Mgr::Inquirer(action,
+ Mgr::ImportHttpFdIntoComm(request.fd), request, strands_));
+ }
+
+ void
+ Ipc::Coordinator::handleCacheMgrResponse(const Mgr::Response& response)
+ {
+ Mgr::Inquirer::HandleRemoteAck(response);
+ }
+
+Comm::ConnectionPointer
Ipc::Coordinator::openListenSocket(const SharedListenRequest& request,
int &errNo)
{
/// returns cached socket or calls openListenSocket()
void handleSharedListenRequest(const SharedListenRequest& request);
+ void handleCacheMgrRequest(const Mgr::Request& request);
+ void handleCacheMgrResponse(const Mgr::Response& response);
/// calls comm_open_listener()
- int openListenSocket(const SharedListenRequest& request, int &errNo);
+ Comm::ConnectionPointer openListenSocket(const SharedListenRequest& request, int &errNo);
private:
- typedef Vector<StrandCoord> Strands; ///< unsorted strands
- Strands strands; ///< registered processes and threads
+ StrandCoords strands_; ///< registered processes and threads
- typedef std::map<OpenListenerParams, int> Listeners; ///< params:fd map
+ typedef std::map<OpenListenerParams, Comm::ConnectionPointer> Listeners; ///< params:fd map
Listeners listeners; ///< cached comm_open_listener() results
static Coordinator* TheInstance; ///< the only class instance in existence
}
Ipc::SharedListenResponse::SharedListenResponse(const TypedMsgHdr &hdrMsg):
- fd(-1), errNo(0), mapId(-1)
+ conn(NULL), errNo(0), mapId(-1)
{
- hdrMsg.getData(mtSharedListenResponse, this, sizeof(*this));
+ hdrMsg.checkType(mtSharedListenResponse);
+ hdrMsg.getPod(*this);
- fd = hdrMsg.getFd();
+ conn = new Comm::Connection;
+ conn->fd = hdrMsg.getFd();
+ // other conn details are passed in OpenListenerParams and filled out by SharedListenJoin()
}
void Ipc::SharedListenResponse::pack(TypedMsgHdr &hdrMsg) const
{
- hdrMsg.putData(mtSharedListenResponse, this, sizeof(*this));
+ hdrMsg.setType(mtSharedListenResponse);
+ hdrMsg.putPod(*this);
- hdrMsg.putFd(fd);
+ hdrMsg.putFd(conn->fd);
}
*/
#include "config.h"
+#include "base/Subscription.h"
#include "base/TextException.h"
+#include "comm/Connection.h"
#include "ipc/Strand.h"
+ #include "ipc/StrandCoord.h"
#include "ipc/Messages.h"
#include "ipc/SharedListen.h"
#include "ipc/Kids.h"
+ #include "mgr/Request.h"
+ #include "mgr/Response.h"
+ #include "mgr/Forwarder.h"
+ #include "CacheManager.h"
-
CBDATA_NAMESPACED_CLASS_INIT(Ipc, Strand);
*/
#include "squid.h"
- #include "CacheManager.h"
#include "cbdata.h"
+#include "CacheManager.h"
+#include "DnsLookupDetails.h"
#include "event.h"
#include "ip/Address.h"
#include "ip/tools.h"
#if defined(USE_SELECT) || defined(USE_SELECT_WIN32)
#include "comm_select.h"
#endif
-#include "SquidTime.h"
-#include "SwapDir.h"
+#include "ConfigParser.h"
+#include "CpuAffinity.h"
+#include "DiskIO/DiskIOModule.h"
+#include "errorpage.h"
+#if USE_SQUID_ESI
+#include "esi/Module.h"
+#endif
+#include "event.h"
+#include "EventLoop.h"
+#include "ExternalACL.h"
#include "forward.h"
-#include "MemPool.h"
+#include "fs/Module.h"
+#include "htcp.h"
+#include "HttpReply.h"
#include "icmp/IcmpSquid.h"
#include "icmp/net_db.h"
-
+#include "ICP.h"
+#include "ident/Ident.h"
+#include "ip/tools.h"
+#include "ipc/Coordinator.h"
+#include "ipc/Kids.h"
+#include "ipc/Strand.h"
+ #if DELAY_POOLS
+ #include "ClientDelayConfig.h"
+ #endif
-
#if USE_LOADABLE_MODULES
#include "LoadableModules.h"
#endif
-
-#if ICAP_CLIENT
-#include "adaptation/icap/Config.h"
-#endif
-#if USE_ECAP
-#include "adaptation/ecap/Config.h"
-#endif
-#if USE_ADAPTATION
-#include "adaptation/Config.h"
-#endif
-#if USE_SQUID_ESI
-#include "esi/Module.h"
-#endif
-#include "fs/Module.h"
+#include "Mem.h"
+#include "MemPool.h"
+#include "pconn.h"
+#include "PeerSelectState.h"
+#include "SquidTime.h"
+#include "Store.h"
+#include "StoreFileSystem.h"
+#include "SwapDir.h"
+ #if HAVE_PATHS_H
+ #include <paths.h>
+ #endif
#if USE_WIN32_SERVICE
-
#include "squid_windows.h"
#include <process.h>
#include "squid.h"
#include "ProtoPort.h"
#include "acl/FilledChecklist.h"
- #include "CacheManager.h"
+#include "comm/Connection.h"
+#include "comm/ConnOpener.h"
#include "event.h"
#include "htcp.h"
#include "HttpRequest.h"
static void
neighborsRegisterWithCacheManager()
{
- CacheManager *manager = CacheManager::GetInstance();
- manager->registerAction("server_list",
- "Peer Cache Statistics",
- neighborDumpPeers, 0, 1);
+ Mgr::RegisterAction("server_list",
+ "Peer Cache Statistics",
+ neighborDumpPeers, 0, 1);
- if (theInIcpConnection >= 0) {
+ if (Comm::IsConnOpen(icpIncomingConn)) {
- manager->registerAction("non_peers",
- "List of Unknown sites sending ICP messages",
- neighborDumpNonPeers, 0, 1);
+ Mgr::RegisterAction("non_peers",
+ "List of Unknown sites sending ICP messages",
+ neighborDumpNonPeers, 0, 1);
}
}
*/
#include "squid.h"
- #include "CacheManager.h"
-#include "mgr/Registration.h"
-#include "Store.h"
#include "comm.h"
-#include "pconn.h"
+#include "comm/Connection.h"
#include "fde.h"
++#include "mgr/Registration.h"
+#include "pconn.h"
+#include "Store.h"
#define PCONN_FDS_SZ 8 /* pconn set size, increase for better memcache hit rate */
#include "squid.h"
#include "auth/UserRequest.h"
- #include "CacheManager.h"
+#include "comm/Connection.h"
+ #include "mgr/Registration.h"
#include "Store.h"
#include "fde.h"
#include "client_side_request.h"
#include "event.h"
#include "StoreClient.h"
#include "auth/UserRequest.h"
- #include "CacheManager.h"
-#include "mgr/Registration.h"
+#include "comm/Connection.h"
#include "Store.h"
#include "HttpRequest.h"
#include "MemObject.h"
#include "MemBuf.h"
#include "SquidMath.h"
#include "SquidTime.h"
+ #include "mgr/CountersAction.h"
+ #include "mgr/FunAction.h"
+ #include "mgr/InfoAction.h"
+ #include "mgr/IntervalAction.h"
+ #include "mgr/IoAction.h"
++#include "mgr/Registration.h"
+ #include "mgr/ServiceTimesAction.h"
/* these are included because they expose stats calls */
/* TODO: provide a self registration mechanism for those classes
*/
#include "squid.h"
+#include "CacheManager.h"
+#include "comm/Connection.h"
#include "event.h"
+#if 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 "MemObject.h"
#include "mem_node.h"
-#include "StoreMeta.h"
-#include "SwapDir.h"
-#if DELAY_POOLS
-#include "DelayPools.h"
-#endif
-#include "Stack.h"
+#include "MemObject.h"
++#include "mgr/Registration.h"
#include "SquidTime.h"
-#include "swap_log_op.h"
+#include "Stack.h"
+#include "stmem.h"
+#include "Store.h"
+#include "StoreClient.h"
+ #include "mgr/StoreIoAction.h"
+#include "StoreMeta.h"
+#include "swap_log_op.h"
+#include "SwapDir.h"
static STMCB storeWriteComplete;
}
void
- CacheManager::registerAction(CacheManagerAction *anAction)
-CacheManager::Start(int fd, HttpRequest * request, StoreEntry * entry)
++CacheManager::Start(const Comm::ConnectionPointer &conn, HttpRequest * request, StoreEntry * entry)
{
return;
}