Split-stack support for ICP, HTCP, SNMP * Make all *_port directives accept the "[ip|hostname|]:port options" format used by http_port. * Remove incoming/outgoing address directives for UDP. Incoming address is now specified on the *_port directive. NOTE: Outgoing address is no longer possible due to split-stack and multiple-port structural changes. Instead use the configured address of the first port directive which has matching protocol family as outgoing address. This retains the ability to configure different listening and sending ports. ALTERNATIVE (not coded here): Could also make the udp_outgoing_address directive mirror the ACL driven style of tcp_outgoing_address. * Added DNS address directives since DNS is not included in these port changes. * Restructure ModPoll, ModSelect to use new list of ports instead of the fixed array. NOTE: added HTCP and HTTPS alongside ICP and HTTP special interval select loop handling. * rename ICP/HTTP incoming_*, *_average and *_poll directives as UDP and TCP since ICP now includes HTCP, and HTTP now includes TCP. Also duplicated documentation for several of them. FUTURE WORK: * comm/ModSelectWin32 needs re-sync with comm/ModSelect * remove NHttpSockets limit and HttpSockets[] global array. === modified file 'src/AccessLogEntry.h' --- src/AccessLogEntry.h 2011-12-16 11:29:40 +0000 +++ src/AccessLogEntry.h 2012-03-02 17:06:39 +0000 @@ -30,6 +30,7 @@ #ifndef SQUID_HTTPACCESSLOGENTRY_H #define SQUID_HTTPACCESSLOGENTRY_H +#include "anyp/PortList.h" #include "comm/Connection.h" #include "HttpVersion.h" #include "HttpRequestMethod.h" @@ -39,7 +40,6 @@ #if ICAP_CLIENT #include "adaptation/icap/Elements.h" #endif -#include "ProtoPort.h" /* forward decls */ class HttpReply; @@ -154,7 +154,7 @@ const char *ssluser; #endif - http_port_list *port; + AnyP::PortList *port; } cache; === modified file 'src/ICP.h' --- src/ICP.h 2011-07-16 15:21:48 +0000 +++ src/ICP.h 2012-03-06 23:56:22 +0000 @@ -109,7 +109,13 @@ /// \ingroup ServerProtocolICPAPI struct icpUdpData { + + /// config details of the peer this packet is being sent to (if any) + const peer *peerDetail; // XXX: cbdata pointer? + + /// IP address for the remote end. Because we reply to packets from unknown non-peers. Ip::Address address; + void *msg; size_t len; icpUdpData *next; @@ -123,15 +129,19 @@ struct timeval queue_time; }; -extern Comm::ConnectionPointer icpIncomingConn; -extern Comm::ConnectionPointer icpOutgoingConn; +/// whether any ICP ports are currently open +extern bool icpActive; + extern Ip::Address theIcpPublicHostID; -/// \ingroup ServerProtocolICPAPI -HttpRequest* icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from); - -/// \ingroup ServerProtocolICPAPI -bool icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request); +/// Locate an open ICP port which can use for packets to the given destination +extern Comm::ConnectionPointer icpLocateOutConn(const Ip::Address &sendingTo); + +/// \ingroup ServerProtocolICPAPI +extern HttpRequest* icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from); + +/// \ingroup ServerProtocolICPAPI +extern bool icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request); /// \ingroup ServerProtocolICPAPI SQUIDCEXTERN void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from); @@ -140,7 +150,7 @@ extern icp_opcode icpGetCommonOpcode(); /// \ingroup ServerProtocolICPAPI -SQUIDCEXTERN int icpUdpSend(int, const Ip::Address &, icp_common_t *, log_type, int); +SQUIDCEXTERN int icpUdpSend(const peer *, const Ip::Address &, icp_common_t *, log_type, int); /// \ingroup ServerProtocolICPAPI SQUIDCEXTERN log_type icpLogFromICPCode(icp_opcode opcode); @@ -161,13 +171,10 @@ SQUIDCEXTERN int icpCheckUdpHit(StoreEntry *, HttpRequest * request); /// \ingroup ServerProtocolICPAPI -SQUIDCEXTERN void icpConnectionsOpen(void); - -/// \ingroup ServerProtocolICPAPI -SQUIDCEXTERN void icpConnectionShutdown(void); - -/// \ingroup ServerProtocolICPAPI -SQUIDCEXTERN void icpConnectionClose(void); +SQUIDCEXTERN void icpOpenPorts(void); + +/// \ingroup ServerProtocolICPAPI +SQUIDCEXTERN void icpClosePorts(void); /// \ingroup ServerProtocolICPAPI SQUIDCEXTERN int icpSetCacheKey(const cache_key * key); === modified file 'src/Makefile.am' --- src/Makefile.am 2012-02-06 01:01:23 +0000 +++ src/Makefile.am 2012-03-02 14:00:28 +0000 @@ -262,8 +262,6 @@ AsyncEngine.cc \ AsyncEngine.h \ cache_cf.cc \ - ProtoPort.cc \ - ProtoPort.h \ CacheDigest.cc \ cache_manager.cc \ CacheManager.h \ @@ -650,7 +648,7 @@ ## ACLProxyAuth.cc wants ACLRegexData ## cache_cf.cc wants $(AUTH_LIBS) ## cache_cf.cc wants Swapdir -## cache_cf.cc wants ProtoPort +## cache_cf.cc wants AnyP::PortList ## client_side wants client_db ## client_db wants SNMP_SOURCE ## snmp_core wants ACLStringData @@ -1266,8 +1264,6 @@ BodyPipe.cc \ cache_manager.cc \ cache_cf.cc \ - ProtoPort.cc \ - ProtoPort.h \ CacheDigest.cc \ carp.cc \ cbdata.cc \ @@ -1675,8 +1671,6 @@ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ - ProtoPort.cc \ - ProtoPort.h \ redirect.cc \ refresh.cc \ RemovalPolicy.cc \ @@ -1869,8 +1863,6 @@ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ - ProtoPort.cc \ - ProtoPort.h \ RemovalPolicy.cc \ redirect.cc \ refresh.cc \ @@ -1974,8 +1966,6 @@ $(ACL_REGISTRATION_SOURCES) \ BodyPipe.cc \ cache_cf.cc \ - ProtoPort.cc \ - ProtoPort.h \ cache_manager.cc \ CacheDigest.cc \ carp.cc \ @@ -2215,8 +2205,6 @@ cache_manager.cc \ cache_cf.cc \ debug.cc \ - ProtoPort.cc \ - ProtoPort.h \ CacheDigest.cc \ carp.cc \ cbdata.cc \ @@ -3195,8 +3183,6 @@ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ - ProtoPort.cc \ - ProtoPort.h \ redirect.cc \ refresh.cc \ RemovalPolicy.cc \ === modified file 'src/StatCounters.h' --- src/StatCounters.h 2011-12-17 01:26:31 +0000 +++ src/StatCounters.h 2012-03-04 02:23:27 +0000 @@ -144,9 +144,9 @@ double cputime; struct timeval timestamp; - StatHist comm_icp_incoming; + StatHist comm_udp_incoming; StatHist comm_dns_incoming; - StatHist comm_http_incoming; + StatHist comm_tcp_incoming; StatHist select_fds_hist; struct { === modified file 'src/acl/Acl.cc' --- src/acl/Acl.cc 2012-01-20 18:55:04 +0000 +++ src/acl/Acl.cc 2012-03-02 14:45:51 +0000 @@ -37,7 +37,7 @@ #include "ConfigParser.h" #include "Debug.h" #include "dlink.h" -#include "ProtoPort.h" +#include "anyp/PortList.h" const char *AclMatchedName = NULL; @@ -123,7 +123,7 @@ // Is this ACL going to work? if (strcmp(theType, "myip") == 0) { - http_port_list *p = Config.Sockaddr.http; + AnyP::PortList *p = Config.Sockaddr.http; while (p) { // Bug 3239: not reliable when there is interception traffic coming if (p->intercepted) @@ -133,7 +133,7 @@ debugs(28, DBG_IMPORTANT, "UPGRADE: ACL 'myip' type is has been renamed to 'localip' and matches the IP the client connected to."); theType = "localip"; } else if (strcmp(theType, "myport") == 0) { - http_port_list *p = Config.Sockaddr.http; + AnyP::PortList *p = Config.Sockaddr.http; while (p) { // Bug 3239: not reliable when there is interception traffic coming // Bug 3239: myport - not reliable (yet) when there is interception traffic coming === modified file 'src/acl/MyPortName.cc' --- src/acl/MyPortName.cc 2012-01-20 18:55:04 +0000 +++ src/acl/MyPortName.cc 2012-03-02 16:52:41 +0000 @@ -34,10 +34,10 @@ */ #include "squid-old.h" -#include "ProtoPort.h" #include "acl/MyPortName.h" #include "acl/StringData.h" #include "acl/Checklist.h" +#include "anyp/PortList.h" #include "HttpRequest.h" /* for ConnStateData */ === modified file 'src/anyp/Makefile.am' --- src/anyp/Makefile.am 2011-07-29 13:12:29 +0000 +++ src/anyp/Makefile.am 2012-03-02 13:59:29 +0000 @@ -4,6 +4,8 @@ noinst_LTLIBRARIES = libanyp.la libanyp_la_SOURCES = \ + PortList.cc \ + PortList.h \ ProtocolType.cc \ ProtocolType.h \ ProtocolVersion.h === renamed file 'src/ProtoPort.cc' => 'src/anyp/PortList.cc' --- src/ProtoPort.cc 2012-01-20 18:55:04 +0000 +++ src/anyp/PortList.cc 2012-03-02 14:05:21 +0000 @@ -1,11 +1,13 @@ #include "squid.h" #include "comm.h" -#include "ProtoPort.h" +#include "anyp/PortList.h" #if HAVE_LIMITS #include #endif -http_port_list::http_port_list(const char *aProtocol) +CBDATA_NAMESPACED_CLASS_INIT(AnyP, PortList); + +AnyP::PortList::PortList(const char *aProtocol) #if USE_SSL : dynamicCertMemCacheSize(std::numeric_limits::max()) @@ -14,7 +16,7 @@ protocol = xstrdup(aProtocol); } -http_port_list::~http_port_list() +AnyP::PortList::~PortList() { if (Comm::IsConnOpen(listenConn)) { listenConn->close(); === renamed file 'src/ProtoPort.h' => 'src/anyp/PortList.h' --- src/ProtoPort.h 2011-12-19 03:51:22 +0000 +++ src/anyp/PortList.h 2012-03-02 13:57:34 +0000 @@ -1,9 +1,5 @@ -/* - * $Id$ - */ - -#ifndef SQUID_PROTO_PORT_H -#define SQUID_PROTO_PORT_H +#ifndef SQUID_ANYP_PORTLIST_H +#define SQUID_ANYP_PORTLIST_H #include "cbdata.h" #include "comm/Connection.h" @@ -12,11 +8,14 @@ #include "ssl/gadgets.h" #endif -struct http_port_list { - http_port_list(const char *aProtocol); - ~http_port_list(); - - http_port_list *next; +namespace AnyP +{ + +struct PortList { + PortList(const char *aProtocol); + ~PortList(); + + PortList *next; Ip::Address s; char *protocol; /* protocol name */ @@ -72,7 +71,9 @@ Ssl::X509_STACK_Pointer certsToChain; ///< x509 certificates to send with the generated cert #endif - CBDATA_CLASS2(http_port_list); + CBDATA_CLASS2(PortList); // namespaced }; -#endif /* SQUID_PROTO_PORT_H */ +} // namespace AnyP + +#endif /* SQUID_ANYP_PORTLIST_H */ === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2012-03-02 03:20:08 +0000 +++ src/cache_cf.cc 2012-03-09 01:01:21 +0000 @@ -46,6 +46,7 @@ #if USE_ECAP #include "adaptation/ecap/Config.h" #endif +#include "anyp/PortList.h" #if USE_SSL #include "ssl/support.h" #include "ssl/Config.h" @@ -71,7 +72,6 @@ #include "MemBuf.h" #include "mgr/Registration.h" #include "Parsing.h" -#include "ProtoPort.h" #include "rfc1738.h" #if SQUID_SNMP #include "snmp.h" @@ -189,17 +189,11 @@ #endif /* CURRENTLY_UNUSED */ #endif /* USE_WCCPv2 */ -static void parsePortList(http_port_list **, const char *protocol); -#define parse_http_port_list(l) parsePortList((l),"http") -static void dump_http_port_list(StoreEntry *, const char *, const http_port_list *); -static void free_http_port_list(http_port_list **); +static void parsePortList(AnyP::PortList **, const char *protocol); -#if USE_SSL -#define parse_https_port_list(l) parsePortList((l),"https") -#define dump_https_port_list(e,n,l) dump_http_port_list((e),(n),(l)) -#define free_https_port_list(l) free_http_port_list((l)) -#define check_null_https_port_list(l) check_null_http_port_list((l)) -#endif /* USE_SSL */ +#define parse_PortList(l) parsePortList((l), token) +static void dump_PortList(StoreEntry *, const char *, const AnyP::PortList *); +static void free_PortList(AnyP::PortList **); static void parse_b_size_t(size_t * var); static void parse_b_int64_t(int64_t * var); @@ -894,9 +888,9 @@ { - http_port_list *s; + AnyP::PortList *s; - for (s = Config.Sockaddr.http; s != NULL; s = (http_port_list *) s->next) { + for (s = Config.Sockaddr.http; s != NULL; s = s->next) { if (!s->cert && !s->key) continue; @@ -910,11 +904,6 @@ Ssl::readCertChainAndPrivateKeyFromFiles(s->signingCert, s->signPkey, s->certsToChain, s->cert, s->key); } - } - - { - - http_port_list *s; for (s = Config.Sockaddr.https; s != NULL; s = s->next) { debugs(3, 1, "Initializing https_port " << s->s << " SSL context"); @@ -3511,10 +3500,8 @@ #endif /* CURRENTLY_UNUSED */ #endif /* USE_WCCPv2 */ -CBDATA_CLASS_INIT(http_port_list); - static void -parsePortSpecification(http_port_list * s, char *token) +parsePortSpecification(AnyP::PortList * s, char *token) { char *host = NULL; unsigned short port = 0; @@ -3588,7 +3575,7 @@ } static void -parse_http_port_option(http_port_list * s, char *token) +parse_port_option(AnyP::PortList * s, char *token) { /* modes first */ @@ -3787,20 +3774,25 @@ } void -add_http_port(char *portspec) +add_generic_port(char *portspec, const char *protocol) { - http_port_list *s = new http_port_list("http"); + AnyP::PortList *s = new AnyP::PortList(protocol); parsePortSpecification(s, portspec); // we may need to merge better of the above returns a list with clones assert(s->next == NULL); - s->next = Config.Sockaddr.http; - Config.Sockaddr.http = s; + if (!strcmp(protocol,"http")) { + s->next = Config.Sockaddr.http; + Config.Sockaddr.http = s; + } else if(!strcmp(protocol,"icp")) { + s->next = Config.Sockaddr.icp; + Config.Sockaddr.icp = s; + } } -http_port_list * -clone_http_port_list(http_port_list *a) +AnyP::PortList * +clone_PortList(AnyP::PortList *a) { - http_port_list *b = new http_port_list(a->protocol); + AnyP::PortList *b = new AnyP::PortList(a->protocol); b->s = a->s; if (a->name) @@ -3824,9 +3816,6 @@ // AYJ: 2009-07-18: for now SSL does not clone. Configure separate ports with IPs and SSL settings #if USE_SSL - // XXX: temporary hack to ease move of SSL options to http_port - http_port_list &http; - char *cert; char *key; int version; @@ -3848,8 +3837,12 @@ } static void -parsePortList(http_port_list ** head, const char *protocol) +parsePortList(AnyP::PortList ** head, const char *type) { + char protocol[15]; + memset(protocol, '\0', sizeof(protocol)); + memcpy(protocol, type, min(sizeof(protocol)-1,strlen(type)-5)); + char *token = strtok(NULL, w_space); if (!token) { @@ -3857,17 +3850,17 @@ return; } - http_port_list *s = new http_port_list(protocol); + AnyP::PortList *s = new AnyP::PortList(protocol); parsePortSpecification(s, token); /* parse options ... */ while ((token = strtok(NULL, w_space))) { - parse_http_port_option(s, token); + parse_port_option(s, token); } if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && s->s.IsAnyAddr()) { // clone the port options from *s to *(s->next) - s->next = clone_http_port_list(s); + s->next = clone_PortList(s); s->next->s.SetIPv4(); debugs(3, 3, protocol << "_port: clone wildcard address for split-stack: " << s->s << " and " << s->next->s); } @@ -3879,7 +3872,7 @@ } static void -dump_generic_http_port(StoreEntry * e, const char *n, const http_port_list * s) +dump_generic_port(StoreEntry * e, const char *n, const AnyP::PortList * s) { char buf[MAX_IPSTRLEN]; @@ -3908,7 +3901,7 @@ if (s->defaultsite) storeAppendPrintf(e, " defaultsite=%s", s->defaultsite); - if (s->protocol && strcmp(s->protocol,"http") != 0) + if (s->protocol && strncmp(s->protocol, n, strlen(s->protocol)) != 0) storeAppendPrintf(e, " protocol=%s", s->protocol); if (s->allow_direct) @@ -4002,19 +3995,19 @@ } static void -dump_http_port_list(StoreEntry * e, const char *n, const http_port_list * s) +dump_PortList(StoreEntry * e, const char *n, const AnyP::PortList * s) { while (s) { - dump_generic_http_port(e, n, s); + dump_generic_port(e, n, s); storeAppendPrintf(e, "\n"); s = s->next; } } static void -free_http_port_list(http_port_list ** head) +free_PortList(AnyP::PortList ** head) { - http_port_list *s; + AnyP::PortList *s; while ((s = *head) != NULL) { *head = s->next; === modified file 'src/cf.data.depend' --- src/cf.data.depend 2011-10-28 19:43:45 +0000 +++ src/cf.data.depend 2012-03-02 14:01:43 +0000 @@ -31,8 +31,6 @@ hostdomaintype cache_peer http_header_access acl http_header_replace -http_port_list -https_port_list adaptation_access_type adaptation_service_set adaptation_service_chain acl icap_service icap_class adaptation_service_set_type icap_service ecap_service adaptation_service_chain_type icap_service ecap_service @@ -52,6 +50,7 @@ onoff peer peer_access cache_peer acl +PortList QosConfig refreshpattern removalpolicy === modified file 'src/cf.data.pre' --- src/cf.data.pre 2012-03-08 04:23:06 +0000 +++ src/cf.data.pre 2012-03-09 01:44:45 +0000 @@ -1279,7 +1279,7 @@ COMMENT_END NAME: http_port ascii_port -TYPE: http_port_list +TYPE: PortList DEFAULT: none LOC: Config.Sockaddr.http DOC_START @@ -1510,7 +1510,7 @@ NAME: https_port IFDEF: USE_SSL -TYPE: https_port_list +TYPE: PortList DEFAULT: none LOC: Config.Sockaddr.https DOC_START @@ -5592,15 +5592,15 @@ COMMENT_END NAME: snmp_port -TYPE: u_short -LOC: Config.Port.snmp -DEFAULT: 0 +TYPE: PortList +DEFAULT: none +LOC: Config.Sockaddr.snmp IFDEF: SQUID_SNMP DOC_START - The port number where Squid listens for SNMP requests. To enable + The port where Squid listens for SNMP requests. To enable SNMP support set this to a suitable port number. Port number - 3401 is often used for the Squid SNMP agent. By default it's - set to "0" (disabled) + 3401 is often used for the Squid SNMP agent. By default it is + disabled. Example: snmp_port 3401 @@ -5627,11 +5627,11 @@ DOC_END NAME: snmp_incoming_address -TYPE: address -LOC: Config.Addrs.snmp_incoming -DEFAULT: any_addr +TYPE: obsolete IFDEF: SQUID_SNMP -DOC_NONE +DOC_START + Use snmp_port instead. It takes address:port as a parameter. +DOC_END NAME: snmp_outgoing_address TYPE: address @@ -5639,9 +5639,9 @@ DEFAULT: no_addr IFDEF: SQUID_SNMP DOC_START - Just like 'udp_incoming_address', but for the SNMP port. + Just like 'udp_outging_address', but for the SNMP port. - snmp_incoming_address is used for the SNMP socket receiving + snmp_port used for the SNMP socket receiving messages from SNMP agents. snmp_outgoing_address is used for SNMP packets returned to SNMP agents. @@ -5664,27 +5664,27 @@ COMMENT_END NAME: icp_port udp_port -TYPE: u_short -DEFAULT: 0 -LOC: Config.Port.icp +TYPE: PortList +DEFAULT: none +LOC: Config.Sockaddr.icp DOC_START - The port number where Squid sends and receives ICP queries to + The address port where Squid sends and receives ICP queries to and from neighbor caches. The standard UDP port for ICP is 3130. - Default is disabled (0). + Default is disabled. Example: - icp_port @DEFAULT_ICP_PORT@ + icp_port 3130 DOC_END NAME: htcp_port IFDEF: USE_HTCP -TYPE: u_short -DEFAULT: 0 -LOC: Config.Port.htcp +TYPE: PortList +DEFAULT: none +LOC: Config.Sockaddr.htcp DOC_START - The port number where Squid sends and receives HTCP queries to + The address and port where Squid sends and receives HTCP queries to and from neighbor caches. To turn it on you want to set it to - 4827. By default it is set to "0" (disabled). + 4827. By default it is disabled. Example: htcp_port 4827 @@ -5702,41 +5702,49 @@ DOC_END NAME: udp_incoming_address +TYPE: obsolete +DOC_START + Use dns_incoming_address for DNS listening address. + Use icp_port, htcp_port, or snmp_port for other UDP protocols address:port settings. +DOC_END + +NAME: dns_incoming_address TYPE: address -LOC:Config.Addrs.udp_incoming +LOC:Config.dns.incomingAddr DEFAULT: any_addr DOC_START - udp_incoming_address is used for UDP packets received from other - caches. + dns_incoming_address is used to listen for DNS packets. The default behavior is to not bind to any specific address. - Only change this if you want to have all UDP queries received on + Only change this if you want to have all DNS queries received on a specific interface/address. - NOTE: udp_incoming_address is used by the ICP, HTCP, and DNS - modules. Altering it will affect all of them in the same manner. - - see also; udp_outgoing_address - - NOTE, udp_incoming_address and udp_outgoing_address can not + see also; dns_outgoing_address + + NOTE, dns_incoming_address and dns_outgoing_address can not have the same value since they both use the same port. DOC_END NAME: udp_outgoing_address +TYPE: obsolete +DOC_START + Use dns_outgoing_address for DNS sending address. + See icp_port, htcp_port, or snmp_port for details on outgoing address for those protocols. +DOC_END + +NAME: dns_outgoing_address TYPE: address -LOC: Config.Addrs.udp_outgoing +LOC: Config.dns.outgoingAddr DEFAULT: no_addr DOC_START - udp_outgoing_address is used for UDP packets sent out to other - caches. + dns_outgoing_address is used for DNS packets sent. The default behavior is to not bind to any specific address. - Instead it will use the same socket as udp_incoming_address. - Only change this if you want to have UDP queries sent using another - address than where this Squid listens for UDP queries from other - caches. + Instead it will use the same socket as dns_incoming_address. + Only change this if you want to have DNS queries sent using another + address than where this Squid listens for DNS responses. NOTE: udp_outgoing_address is used by the ICP, HTCP, and DNS modules. Altering it will affect all of them in the same manner. @@ -6307,40 +6315,60 @@ ----------------------------------------------------------------------------- COMMENT_END -NAME: incoming_icp_average +NAME: incoming_udp_average incoming_icp_average TYPE: int DEFAULT: 6 -LOC: Config.comm_incoming.icp_average -DOC_NONE +LOC: Config.comm_incoming.udp_average +DOC_START + Heavy voodoo here. I can't even believe you are reading this. + Are you crazy? Don't even think about adjusting these unless + you understand the algorithms in comm_select.c first! +DOC_END -NAME: incoming_http_average +NAME: incoming_tcp_average incoming_http_average TYPE: int DEFAULT: 4 -LOC: Config.comm_incoming.http_average -DOC_NONE +LOC: Config.comm_incoming.tcp_average +DOC_START + Heavy voodoo here. I can't even believe you are reading this. + Are you crazy? Don't even think about adjusting these unless + you understand the algorithms in comm_select.c first! +DOC_END NAME: incoming_dns_average TYPE: int DEFAULT: 4 LOC: Config.comm_incoming.dns_average -DOC_NONE +DOC_START + Heavy voodoo here. I can't even believe you are reading this. + Are you crazy? Don't even think about adjusting these unless + you understand the algorithms in comm_select.c first! +DOC_END -NAME: min_icp_poll_cnt +NAME: min_udp_poll_cnt min_icp_poll_cnt TYPE: int DEFAULT: 8 -LOC: Config.comm_incoming.icp_min_poll -DOC_NONE +LOC: Config.comm_incoming.udp_min_poll +DOC_START + Heavy voodoo here. I can't even believe you are reading this. + Are you crazy? Don't even think about adjusting these unless + you understand the algorithms in comm_select.c first! +DOC_END NAME: min_dns_poll_cnt TYPE: int DEFAULT: 8 LOC: Config.comm_incoming.dns_min_poll -DOC_NONE +DOC_START + Heavy voodoo here. I can't even believe you are reading this. + Are you crazy? Don't even think about adjusting these unless + you understand the algorithms in comm_select.c first! +DOC_END -NAME: min_http_poll_cnt +NAME: min_tcp_poll_cnt min_http_poll_cnt TYPE: int DEFAULT: 8 -LOC: Config.comm_incoming.http_min_poll +LOC: Config.comm_incoming.tcp_min_poll DOC_START Heavy voodoo here. I can't even believe you are reading this. Are you crazy? Don't even think about adjusting these unless === modified file 'src/client_side.cc' --- src/client_side.cc 2012-02-28 17:52:21 +0000 +++ src/client_side.cc 2012-03-03 03:42:33 +0000 @@ -87,6 +87,7 @@ #if USE_AUTH #include "auth/UserRequest.h" #endif +#include "anyp/PortList.h" #include "base/Subscription.h" #include "base/TextException.h" #include "ChunkedCodingParser.h" @@ -115,7 +116,6 @@ #include "ipc/StartListening.h" #include "MemBuf.h" #include "MemObject.h" -#include "ProtoPort.h" #include "rfc1738.h" #include "StatCounters.h" #include "StatHist.h" @@ -145,8 +145,8 @@ class ListeningStartedDialer: public CallDialer, public Ipc::StartListeningCb { public: - typedef void (*Handler)(http_port_list *portCfg, const Ipc::FdNoteId note, const Subscription::Pointer &sub); - ListeningStartedDialer(Handler aHandler, http_port_list *aPortCfg, const Ipc::FdNoteId note, const Subscription::Pointer &aSub): + typedef void (*Handler)(AnyP::PortList *portCfg, const Ipc::FdNoteId note, const Subscription::Pointer &sub); + ListeningStartedDialer(Handler aHandler, AnyP::PortList *aPortCfg, const Ipc::FdNoteId note, const Subscription::Pointer &aSub): handler(aHandler), portCfg(aPortCfg), portTypeNote(note), sub(aSub) {} virtual void print(std::ostream &os) const { @@ -161,12 +161,12 @@ Handler handler; private: - http_port_list *portCfg; ///< from Config.Sockaddr.http + AnyP::PortList *portCfg; ///< from Config.Sockaddr.http Ipc::FdNoteId portTypeNote; ///< Type of IPC socket being opened Subscription::Pointer sub; ///< The handler to be subscribed for this connetion listener }; -static void clientListenerConnectionOpened(http_port_list *s, const Ipc::FdNoteId portTypeNote, const Subscription::Pointer &sub); +static void clientListenerConnectionOpened(AnyP::PortList *s, const Ipc::FdNoteId portTypeNote, const Subscription::Pointer &sub); /* our socket-related context */ @@ -225,7 +225,7 @@ char *skipLeadingSpace(char *aString); static void connNoteUseOfBuffer(ConnStateData* conn, size_t byteCount); -static ConnStateData *connStateCreate(const Comm::ConnectionPointer &client, http_port_list *port); +static ConnStateData *connStateCreate(const Comm::ConnectionPointer &client, AnyP::PortList *port); clientStreamNode * @@ -3148,7 +3148,7 @@ } ConnStateData * -connStateCreate(const Comm::ConnectionPointer &client, http_port_list *port) +connStateCreate(const Comm::ConnectionPointer &client, AnyP::PortList *port) { ConnStateData *result = new ConnStateData; @@ -3210,7 +3210,7 @@ void httpAccept(const CommAcceptCbParams ¶ms) { - http_port_list *s = (http_port_list *)params.data; + AnyP::PortList *s = static_cast(params.data); if (params.flag != COMM_OK) { // Its possible the call was still queued when the client disconnected @@ -3431,7 +3431,7 @@ static void httpsAccept(const CommAcceptCbParams ¶ms) { - http_port_list *s = (http_port_list *)params.data; + AnyP::PortList *s = static_cast(params.data); if (params.flag != COMM_OK) { // Its possible the call was still queued when the client disconnected @@ -3632,7 +3632,7 @@ static void clientHttpConnectionsOpen(void) { - http_port_list *s = NULL; + AnyP::PortList *s = NULL; for (s = Config.Sockaddr.http; s; s = s->next) { if (MAXHTTPPORTS == NHttpSockets) { @@ -3680,7 +3680,7 @@ static void clientHttpsConnectionsOpen(void) { - http_port_list *s; + AnyP::PortList *s; for (s = Config.Sockaddr.https; s; s = s->next) { if (MAXHTTPPORTS == NHttpSockets) { @@ -3717,7 +3717,7 @@ /// process clientHttpConnectionsOpen result static void -clientListenerConnectionOpened(http_port_list *s, const Ipc::FdNoteId portTypeNote, const Subscription::Pointer &sub) +clientListenerConnectionOpened(AnyP::PortList *s, const Ipc::FdNoteId portTypeNote, const Subscription::Pointer &sub) { if (!OpenedHttpSocket(s->listenConn, portTypeNote)) return; @@ -3754,7 +3754,7 @@ void clientHttpConnectionsClose(void) { - for (http_port_list *s = Config.Sockaddr.http; s; s = s->next) { + for (AnyP::PortList *s = Config.Sockaddr.http; s; s = s->next) { if (s->listenConn != NULL) { debugs(1, 1, "Closing HTTP port " << s->listenConn->local); s->listenConn->close(); @@ -3763,7 +3763,7 @@ } #if USE_SSL - for (http_port_list *s = Config.Sockaddr.https; s; s = s->next) { + for (AnyP::PortList *s = Config.Sockaddr.https; s; s = s->next) { if (s->listenConn != NULL) { debugs(1, 1, "Closing HTTPS port " << s->listenConn->local); s->listenConn->close(); === modified file 'src/client_side.h' --- src/client_side.h 2011-12-30 01:24:57 +0000 +++ src/client_side.h 2012-03-02 14:59:55 +0000 @@ -254,7 +254,7 @@ AsyncCall::Pointer closeHandler; /*The close handler for pinned server side connection*/ } pinning; - http_port_list *port; + AnyP::PortList *port; bool transparent() const; bool reading() const; === modified file 'src/client_side_reply.cc' --- src/client_side_reply.cc 2012-01-22 14:15:59 +0000 +++ src/client_side_reply.cc 2012-03-03 03:53:28 +0000 @@ -40,6 +40,7 @@ #include "squid-old.h" #include "acl/FilledChecklist.h" #include "acl/Gadgets.h" +#include "anyp/PortList.h" #if USE_AUTH #include "auth/UserRequest.h" #endif @@ -61,7 +62,6 @@ #include "ip/QosConfig.h" #include "ipcache.h" #include "MemObject.h" -#include "ProtoPort.h" #include "SquidTime.h" #include "StoreClient.h" #include "Store.h" === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2012-02-03 04:07:36 +0000 +++ src/client_side_request.cc 2012-03-03 04:03:37 +0000 @@ -54,6 +54,7 @@ #include "adaptation/icap/History.h" #endif #endif +#include "anyp/PortList.h" #if USE_AUTH #include "auth/UserRequest.h" #endif @@ -72,7 +73,6 @@ #include "HttpRequest.h" #include "ip/QosConfig.h" #include "MemObject.h" -#include "ProtoPort.h" #include "Store.h" #include "SquidTime.h" #include "wordlist.h" === modified file 'src/comm/Loops.h' --- src/comm/Loops.h 2012-02-12 13:15:51 +0000 +++ src/comm/Loops.h 2012-03-04 02:36:37 +0000 @@ -31,6 +31,37 @@ extern void QuickPollRequired(void); +/** + * Max number of UDP messages to receive per call to the UDP receive poller. + * This is a per-port limit for ICP/HTCP ports. + * DNS has a separate limit. + */ +#if _SQUID_MSWIN_ +#define INCOMING_UDP_MAX 1 +#else +#define INCOMING_UDP_MAX 15 +#endif + +/** + * Max number of DNS messages to receive per call to DNS read handler + */ +#if _SQUID_MSWIN_ +#define INCOMING_DNS_MAX 1 +#else +#define INCOMING_DNS_MAX 15 +#endif + +/** + * Max number of new TCP connections to accept per call to the TCP listener poller. + * This is a per-port limit for HTTP/HTTPS ports. + */ +#if _SQUID_MSWIN_ +#define INCOMING_TCP_MAX 1 +#else +#define INCOMING_TCP_MAX 10 +#endif +#define INCOMING_TOTAL_MAX (INCOMING_ICP_MAX+INCOMING_HTTP_MAX) + } // namespace Comm #endif /* _SQUID_SRC_COMM_LOOPS_H */ === modified file 'src/comm/Makefile.am' --- src/comm/Makefile.am 2011-08-17 23:59:03 +0000 +++ src/comm/Makefile.am 2012-03-03 14:09:50 +0000 @@ -23,6 +23,7 @@ ModSelectWin32.cc \ TcpAcceptor.cc \ TcpAcceptor.h \ + UdpOpenDialer.h \ Write.cc \ Write.h \ \ === modified file 'src/comm/ModPoll.cc' --- src/comm/ModPoll.cc 2012-01-20 18:55:04 +0000 +++ src/comm/ModPoll.cc 2012-03-04 02:42:13 +0000 @@ -35,6 +35,7 @@ #if USE_POLL #include "squid-old.h" +#include "anyp/PortList.h" #include "comm/Connection.h" #include "comm/Loops.h" #include "fde.h" @@ -70,8 +71,8 @@ #define FD_MASK_BITS (FD_MASK_BYTES*NBBY) /* STATIC */ -static int fdIsHttp(int fd); -static int fdIsIcp(int fd); +static int fdIsTcpListen(int fd); +static int fdIsUdpListen(int fd); static int fdIsDns(int fd); static OBJH commIncomingStats; static int comm_check_incoming_poll_handlers(int nfds, int *fds); @@ -92,7 +93,7 @@ * multipled by a factor of (2^INCOMING_FACTOR) to have some * pseudo-floating point precision. * - * The variable 'icp_io_events' and 'http_io_events' counts how many normal + * The variable 'udp_io_events' and 'tcp_io_events' counts how many normal * I/O events have been processed since the last check on the incoming * sockets. When io_events > incoming_interval, its time to check incoming * sockets. @@ -106,7 +107,7 @@ * * incoming_interval = incoming_interval + target_average - number_of_events_processed * - * There are separate incoming_interval counters for both HTTP and ICP events + * There are separate incoming_interval counters for TCP-based, UDP-based, and DNS events * * You can see the current values of the incoming_interval's, as well as * a histogram of 'incoming_events' by asking the cache manager @@ -128,15 +129,15 @@ #define MAX_INCOMING_INTEGER 256 #define INCOMING_FACTOR 5 #define MAX_INCOMING_INTERVAL (MAX_INCOMING_INTEGER << INCOMING_FACTOR) -static int icp_io_events = 0; -static int dns_io_events = 0; -static int http_io_events = 0; -static int incoming_icp_interval = 16 << INCOMING_FACTOR; +static int udp_io_events = 0; ///< I/O events passed since last UDP receiver socket poll +static int dns_io_events = 0; ///< I/O events passed since last DNS socket poll +static int tcp_io_events = 0; ///< I/O events passed since last TCP listening socket poll +static int incoming_udp_interval = 16 << INCOMING_FACTOR; static int incoming_dns_interval = 16 << INCOMING_FACTOR; -static int incoming_http_interval = 16 << INCOMING_FACTOR; -#define commCheckICPIncoming (++icp_io_events > (incoming_icp_interval>> INCOMING_FACTOR)) -#define commCheckDNSIncoming (++dns_io_events > (incoming_dns_interval>> INCOMING_FACTOR)) -#define commCheckHTTPIncoming (++http_io_events > (incoming_http_interval>> INCOMING_FACTOR)) +static int incoming_tcp_interval = 16 << INCOMING_FACTOR; +#define commCheckUdpIncoming (++udp_io_events > (incoming_udp_interval>> INCOMING_FACTOR)) +#define commCheckDnsIncoming (++dns_io_events > (incoming_dns_interval>> INCOMING_FACTOR)) +#define commCheckTcpIncoming (++tcp_io_events > (incoming_tcp_interval>> INCOMING_FACTOR)) void @@ -169,13 +170,19 @@ } static int -fdIsIcp(int fd) +fdIsUdpListen(int fd) { - if (icpIncomingConn != NULL && icpIncomingConn->fd == fd) - return 1; +#if USE_HTCP + for (const AnyP::PortList *s = Config.Sockaddr.htcp; s; s = s->next) { + if (s->listenConn != NULL && s->listenConn->fd == fd) + return 1; + } +#endif - if (icpOutgoingConn != NULL && icpOutgoingConn->fd == fd) - return 1; + for (const AnyP::PortList *s = Config.Sockaddr.icp; s; s = s->next) { + if (s->listenConn != NULL && s->listenConn->fd == fd) + return 1; + } return 0; } @@ -193,14 +200,19 @@ } static int -fdIsHttp(int fd) +fdIsTcpListen(int fd) { - int j; + for (const AnyP::PortList *s = Config.Sockaddr.http; s; s = s->next) { + if (s->listenConn != NULL && s->listenConn->fd == fd) + return 1; + } - for (j = 0; j < NHttpSockets; j++) { - if (fd == HttpSockets[j]) +#if SQUID_SSL + for (const AnyP::PortList *s = Config.Sockaddr.https; s; s = s->next) { + if (s->listenConn != NULL && s->listenConn->fd == fd) return 1; } +#endif return 0; } @@ -277,70 +289,81 @@ } static void -comm_poll_icp_incoming(void) +comm_poll_udp_incoming(void) { int nfds = 0; int fds[2]; int nevents; - icp_io_events = 0; - - if (Comm::IsConnOpen(icpIncomingConn)) - fds[nfds++] = icpIncomingConn->fd; - - if (icpIncomingConn != icpOutgoingConn && Comm::IsConnOpen(icpOutgoingConn)) - fds[nfds++] = icpOutgoingConn->fd; + udp_io_events = 0; + +#if USE_HTCP + for (const AnyP::PortList *s = Config.Sockaddr.htcp; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn)) + fds[nfds++] = s->listenConn->fd; + } +#endif + + for (const AnyP::PortList *s = Config.Sockaddr.icp; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn)) + fds[nfds++] = s->listenConn->fd; + } if (nfds == 0) return; nevents = comm_check_incoming_poll_handlers(nfds, fds); - incoming_icp_interval += Config.comm_incoming.icp_average - nevents; - - if (incoming_icp_interval < Config.comm_incoming.icp_min_poll) - incoming_icp_interval = Config.comm_incoming.icp_min_poll; - - if (incoming_icp_interval > MAX_INCOMING_INTERVAL) - incoming_icp_interval = MAX_INCOMING_INTERVAL; - - if (nevents > INCOMING_ICP_MAX) - nevents = INCOMING_ICP_MAX; - - statCounter.comm_icp_incoming.count(nevents); + incoming_udp_interval += Config.comm_incoming.udp_average - nevents; + + if (incoming_udp_interval < Config.comm_incoming.udp_min_poll) + incoming_udp_interval = Config.comm_incoming.udp_min_poll; + + if (incoming_udp_interval > MAX_INCOMING_INTERVAL) + incoming_udp_interval = MAX_INCOMING_INTERVAL; + + if (nevents > INCOMING_UDP_MAX) + nevents = INCOMING_UDP_MAX; + + statCounter.comm_udp_incoming.count(nevents); } static void -comm_poll_http_incoming(void) +comm_poll_tcp_incoming(void) { int nfds = 0; int fds[MAXHTTPPORTS]; int j; int nevents; - http_io_events = 0; - - /* only poll sockets that won't be deferred */ - - for (j = 0; j < NHttpSockets; j++) { - if (HttpSockets[j] < 0) - continue; - - fds[nfds++] = HttpSockets[j]; - } + tcp_io_events = 0; + + // XXX: only poll sockets that won't be deferred. But how do we identify them? + + for (const AnyP::PortList *s = Config.Sockaddr.http; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn)) + fds[nfds++] = s->listenConn->fd; + } + +#if SQUID_SSL + for (const AnyP::PortList *s = Config.Sockaddr.https; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn)) + fds[nfds++] = s->listenConn->fd; + } +#endif nevents = comm_check_incoming_poll_handlers(nfds, fds); - incoming_http_interval = incoming_http_interval - + Config.comm_incoming.http_average - nevents; - - if (incoming_http_interval < Config.comm_incoming.http_min_poll) - incoming_http_interval = Config.comm_incoming.http_min_poll; - - if (incoming_http_interval > MAX_INCOMING_INTERVAL) - incoming_http_interval = MAX_INCOMING_INTERVAL; - - if (nevents > INCOMING_HTTP_MAX) - nevents = INCOMING_HTTP_MAX; - - statCounter.comm_http_incoming.count(nevents); + incoming_tcp_interval = incoming_tcp_interval + + Config.comm_incoming.tcp_average - nevents; + + if (incoming_tcp_interval < Config.comm_incoming.tcp_min_poll) + incoming_tcp_interval = Config.comm_incoming.tcp_min_poll; + + if (incoming_tcp_interval > MAX_INCOMING_INTERVAL) + incoming_tcp_interval = MAX_INCOMING_INTERVAL; + + if (nevents > INCOMING_TCP_MAX) + nevents = INCOMING_TCP_MAX; + + statCounter.comm_tcp_incoming.count(nevents); } /* poll all sockets; call handlers for those that are ready. */ @@ -355,8 +378,7 @@ unsigned long nfds; unsigned long npending; int num; - int callicp = 0, callhttp = 0; - int calldns = 0; + int calldns = 0, calludp = 0, calltcp = 0; double timeout = current_dtime + (msec / 1000.0); do { @@ -364,18 +386,18 @@ getCurrentTime(); start = current_dtime; - if (commCheckICPIncoming) - comm_poll_icp_incoming(); - - if (commCheckDNSIncoming) + if (commCheckDnsIncoming) comm_poll_dns_incoming(); - if (commCheckHTTPIncoming) - comm_poll_http_incoming(); + if (commCheckUdpIncoming) + comm_poll_udp_incoming(); + + if (commCheckTcpIncoming) + comm_poll_tcp_incoming(); PROF_start(comm_poll_prep_pfds); - callicp = calldns = callhttp = 0; + calldns = calludp = calltcp = 0; nfds = 0; @@ -474,18 +496,18 @@ if (revents == 0) continue; - if (fdIsIcp(fd)) { - callicp = 1; - continue; - } - if (fdIsDns(fd)) { calldns = 1; continue; } - if (fdIsHttp(fd)) { - callhttp = 1; + if (fdIsUdpListen(fd)) { + calludp = 1; + continue; + } + + if (fdIsTcpListen(fd)) { + calltcp = 1; continue; } @@ -494,9 +516,7 @@ if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { debugs(5, 6, "comm_poll: FD " << fd << " ready for reading"); - if (NULL == (hdl = F->read_handler)) - (void) 0; - else { + if ((hdl = F->read_handler)) { PROF_start(comm_read_handler); F->read_handler = NULL; F->flags.read_pending = 0; @@ -504,14 +524,14 @@ PROF_stop(comm_read_handler); statCounter.select_fds++; - if (commCheckICPIncoming) - comm_poll_icp_incoming(); - - if (commCheckDNSIncoming) + if (commCheckDnsIncoming) comm_poll_dns_incoming(); - if (commCheckHTTPIncoming) - comm_poll_http_incoming(); + if (commCheckUdpIncoming) + comm_poll_udp_incoming(); + + if (commCheckTcpIncoming) + comm_poll_tcp_incoming(); } } @@ -525,14 +545,14 @@ PROF_stop(comm_write_handler); statCounter.select_fds++; - if (commCheckICPIncoming) - comm_poll_icp_incoming(); - - if (commCheckDNSIncoming) + if (commCheckDnsIncoming) comm_poll_dns_incoming(); - if (commCheckHTTPIncoming) - comm_poll_http_incoming(); + if (commCheckUdpIncoming) + comm_poll_udp_incoming(); + + if (commCheckTcpIncoming) + comm_poll_tcp_incoming(); } } @@ -566,14 +586,14 @@ PROF_stop(comm_handle_ready_fd); - if (callicp) - comm_poll_icp_incoming(); - if (calldns) comm_poll_dns_incoming(); - if (callhttp) - comm_poll_http_incoming(); + if (calludp) + comm_poll_udp_incoming(); + + if (calltcp) + comm_poll_tcp_incoming(); getCurrentTime(); @@ -642,20 +662,20 @@ static void commIncomingStats(StoreEntry * sentry) { - storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n", - incoming_icp_interval >> INCOMING_FACTOR); + storeAppendPrintf(sentry, "Current incoming_udp_interval: %d\n", + incoming_udp_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n", incoming_dns_interval >> INCOMING_FACTOR); - storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n", - incoming_http_interval >> INCOMING_FACTOR); + storeAppendPrintf(sentry, "Current incoming_tcp_interval: %d\n", + incoming_tcp_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n"); - storeAppendPrintf(sentry, "ICP Messages handled per comm_poll_icp_incoming() call:\n"); - statCounter.comm_icp_incoming.dump(sentry, statHistIntDumper); + storeAppendPrintf(sentry, "HTCP/ICP Messages handled per comm_poll_udp_incoming() call:\n"); + statCounter.comm_udp_incoming.dump(sentry, statHistIntDumper); storeAppendPrintf(sentry, "DNS Messages handled per comm_poll_dns_incoming() call:\n"); statCounter.comm_dns_incoming.dump(sentry, statHistIntDumper); - storeAppendPrintf(sentry, "HTTP Messages handled per comm_poll_http_incoming() call:\n"); - statCounter.comm_http_incoming.dump(sentry, statHistIntDumper); + storeAppendPrintf(sentry, "HTTP/HTTPS Messages handled per comm_poll_tcp_incoming() call:\n"); + statCounter.comm_tcp_incoming.dump(sentry, statHistIntDumper); } /* Called by async-io or diskd to speed up the polling */ === modified file 'src/comm/ModSelect.cc' --- src/comm/ModSelect.cc 2012-03-09 02:09:33 +0000 +++ src/comm/ModSelect.cc 2012-03-09 02:12:56 +0000 @@ -35,9 +35,11 @@ #if USE_SELECT #include "squid-old.h" +#include "anyp/PortList.h" #include "comm/Connection.h" #include "comm/Loops.h" #include "fde.h" +#include "htcp.h" #include "ICP.h" #include "mgr/Registration.h" #include "SquidTime.h" @@ -58,8 +60,8 @@ /* STATIC */ static int examine_select(fd_set *, fd_set *); -static int fdIsHttp(int fd); -static int fdIsIcp(int fd); +static int fdIsTcpListener(int fd); +static int fdIsUdpListener(int fd); static int fdIsDns(int fd); static OBJH commIncomingStats; static int comm_check_incoming_select_handlers(int nfds, int *fds); @@ -77,19 +79,19 @@ /* * Automatic tuning for incoming requests: * - * INCOMING sockets are the ICP and HTTP ports. We need to check these + * INCOMING sockets are the HTCP, ICP, HTTP and HTTPS ports. We need to check these * fairly regularly, but how often? When the load increases, we * want to check the incoming sockets more often. If we have a lot * of incoming ICP, then we need to check these sockets more than * if we just have HTTP. * - * The variables 'incoming_icp_interval' and 'incoming_http_interval' + * The variables 'incoming_udp_interval' and 'incoming_tcp_interval' * determine how many normal I/O events to process before checking * incoming sockets again. Note we store the incoming_interval * multipled by a factor of (2^INCOMING_FACTOR) to have some * pseudo-floating point precision. * - * The variable 'icp_io_events' and 'http_io_events' counts how many normal + * The variable 'udp_io_events' and 'tcp_io_events' counts how many normal * I/O events have been processed since the last check on the incoming * sockets. When io_events > incoming_interval, its time to check incoming * sockets. @@ -103,7 +105,7 @@ * * incoming_interval = incoming_interval + target_average - number_of_events_processed * - * There are separate incoming_interval counters for both HTTP and ICP events + * There are separate incoming_interval counters for DNS, UDP and TCP events * * You can see the current values of the incoming_interval's, as well as * a histogram of 'incoming_events' by asking the cache manager @@ -125,15 +127,15 @@ #define MAX_INCOMING_INTEGER 256 #define INCOMING_FACTOR 5 #define MAX_INCOMING_INTERVAL (MAX_INCOMING_INTEGER << INCOMING_FACTOR) -static int icp_io_events = 0; +static int udp_io_events = 0; static int dns_io_events = 0; -static int http_io_events = 0; -static int incoming_icp_interval = 16 << INCOMING_FACTOR; +static int tcp_io_events = 0; +static int incoming_udp_interval = 16 << INCOMING_FACTOR; static int incoming_dns_interval = 16 << INCOMING_FACTOR; -static int incoming_http_interval = 16 << INCOMING_FACTOR; -#define commCheckICPIncoming (++icp_io_events > (incoming_icp_interval>> INCOMING_FACTOR)) -#define commCheckDNSIncoming (++dns_io_events > (incoming_dns_interval>> INCOMING_FACTOR)) -#define commCheckHTTPIncoming (++http_io_events > (incoming_http_interval>> INCOMING_FACTOR)) +static int incoming_tcp_interval = 16 << INCOMING_FACTOR; +#define commCheckUdpIncoming (++udp_io_events > (incoming_udp_interval>> INCOMING_FACTOR)) +#define commCheckDnsIncoming (++dns_io_events > (incoming_dns_interval>> INCOMING_FACTOR)) +#define commCheckTcpIncoming (++tcp_io_events > (incoming_tcp_interval>> INCOMING_FACTOR)) void Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout) @@ -167,13 +169,19 @@ } static int -fdIsIcp(int fd) +fdIsUdpListener(int fd) { - if (icpIncomingConn != NULL && fd == icpIncomingConn->fd) - return 1; +#if USE_HTCP + for (const AnyP::PortList *s = Config.Sockaddr.htcp; s; s = s->next) { + if (s->listenConn != NULL && s->listenConn->fd == fd) + return 1; + } +#endif - if (icpOutgoingConn != NULL && fd == icpOutgoingConn->fd) - return 1; + for (const AnyP::PortList *s = Config.Sockaddr.icp; s; s = s->next) { + if (s->listenConn != NULL && s->listenConn->fd == fd) + return 1; + } return 0; } @@ -191,14 +199,19 @@ } static int -fdIsHttp(int fd) +fdIsTcpListener(int fd) { - int j; + for (const AnyP::PortList *s = Config.Sockaddr.http; s; s = s->next) { + if (s->listenConn != NULL && s->listenConn->fd == fd) + return 1; + } - for (j = 0; j < NHttpSockets; j++) { - if (fd == HttpSockets[j]) +#if SQUID_SSL + for (const AnyP::PortList *s = Config.Sockaddr.https; s; s = s->next) { + if (s->listenConn != NULL && s->listenConn->fd == fd) return 1; } +#endif return 0; } @@ -272,67 +285,79 @@ } static void -comm_select_icp_incoming(void) +comm_select_udp_incoming(void) { int nfds = 0; int fds[2]; int nevents; - icp_io_events = 0; - - if (Comm::IsConnOpen(icpIncomingConn)) - fds[nfds++] = icpIncomingConn->fd; - - if (Comm::IsConnOpen(icpOutgoingConn) && icpIncomingConn != icpOutgoingConn) - fds[nfds++] = icpOutgoingConn->fd; + udp_io_events = 0; + +#if USE_HTCP + for (const AnyP::PortList *s = Config.Sockaddr.htcp; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn)) + fds[nfds++] = s->listenConn->fd; + } +#endif + + for (const AnyP::PortList *s = Config.Sockaddr.icp; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn)) + fds[nfds++] = s->listenConn->fd; + } if (nfds == 0) return; nevents = comm_check_incoming_select_handlers(nfds, fds); - incoming_icp_interval += Config.comm_incoming.icp_average - nevents; - - if (incoming_icp_interval < 0) - incoming_icp_interval = 0; - - if (incoming_icp_interval > MAX_INCOMING_INTERVAL) - incoming_icp_interval = MAX_INCOMING_INTERVAL; - - if (nevents > INCOMING_ICP_MAX) - nevents = INCOMING_ICP_MAX; - - statCounter.comm_icp_incoming.count(nevents); + incoming_udp_interval += Config.comm_incoming.udp_average - nevents; + + if (incoming_udp_interval < 0) + incoming_udp_interval = 0; + + if (incoming_udp_interval > MAX_INCOMING_INTERVAL) + incoming_udp_interval = MAX_INCOMING_INTERVAL; + + if (nevents > INCOMING_UDP_MAX) + nevents = INCOMING_UDP_MAX; + + statCounter.comm_udp_incoming.count(nevents); } static void -comm_select_http_incoming(void) +comm_select_tcp_incoming(void) { int nfds = 0; int fds[MAXHTTPPORTS]; - int j; int nevents; - http_io_events = 0; - - for (j = 0; j < NHttpSockets; j++) { - if (HttpSockets[j] < 0) - continue; - - fds[nfds++] = HttpSockets[j]; - } + tcp_io_events = 0; + + // XXX: only poll sockets that won't be deferred. But how do we identify them? + + for (const AnyP::PortList *s = Config.Sockaddr.http; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn)) + fds[nfds++] = s->listenConn->fd; + } + +#if SQUID_SSL + for (const AnyP::PortList *s = Config.Sockaddr.https; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn)) + fds[nfds++] = s->listenConn->fd; + } +#endif nevents = comm_check_incoming_select_handlers(nfds, fds); - incoming_http_interval += Config.comm_incoming.http_average - nevents; - - if (incoming_http_interval < 0) - incoming_http_interval = 0; - - if (incoming_http_interval > MAX_INCOMING_INTERVAL) - incoming_http_interval = MAX_INCOMING_INTERVAL; - - if (nevents > INCOMING_HTTP_MAX) - nevents = INCOMING_HTTP_MAX; - - statCounter.comm_http_incoming.count(nevents); + incoming_tcp_interval += Config.comm_incoming.tcp_average - nevents; + + if (incoming_tcp_interval < 0) + incoming_tcp_interval = 0; + + if (incoming_tcp_interval > MAX_INCOMING_INTERVAL) + incoming_tcp_interval = MAX_INCOMING_INTERVAL; + + if (nevents > INCOMING_TCP_MAX) + nevents = INCOMING_TCP_MAX; + + statCounter.comm_tcp_incoming.count(nevents); } #define DEBUG_FDBITS 0 @@ -349,7 +374,7 @@ int maxfd; int num; int pending; - int callicp = 0, callhttp = 0; + int calludp = 0, calltcp = 0; int calldns = 0; int maxindex; unsigned int k; @@ -372,16 +397,16 @@ getCurrentTime(); start = current_dtime; - if (commCheckICPIncoming) - comm_select_icp_incoming(); + if (commCheckUdpIncoming) + comm_select_udp_incoming(); - if (commCheckDNSIncoming) + if (commCheckDnsIncoming) comm_select_dns_incoming(); - if (commCheckHTTPIncoming) - comm_select_http_incoming(); + if (commCheckTcpIncoming) + comm_select_tcp_incoming(); - callicp = calldns = callhttp = 0; + calludp = calldns = calltcp = 0; maxfd = Biggest_FD + 1; @@ -508,8 +533,8 @@ #endif - if (fdIsIcp(fd)) { - callicp = 1; + if (fdIsUdpListener(fd)) { + calludp = 1; continue; } @@ -518,8 +543,8 @@ continue; } - if (fdIsHttp(fd)) { - callhttp = 1; + if (fdIsTcpListener(fd)) { + calltcp = 1; continue; } @@ -535,14 +560,14 @@ hdl(fd, F->read_data); statCounter.select_fds++; - if (commCheckICPIncoming) - comm_select_icp_incoming(); + if (commCheckUdpIncoming) + comm_select_udp_incoming(); - if (commCheckDNSIncoming) + if (commCheckDnsIncoming) comm_select_dns_incoming(); - if (commCheckHTTPIncoming) - comm_select_http_incoming(); + if (commCheckTcpIncoming) + comm_select_tcp_incoming(); } } } @@ -573,8 +598,8 @@ #endif - if (fdIsIcp(fd)) { - callicp = 1; + if (fdIsUdpListener(fd)) { + calludp = 1; continue; } @@ -583,8 +608,8 @@ continue; } - if (fdIsHttp(fd)) { - callhttp = 1; + if (fdIsTcpListener(fd)) { + calltcp = 1; continue; } @@ -597,26 +622,26 @@ hdl(fd, F->write_data); statCounter.select_fds++; - if (commCheckICPIncoming) - comm_select_icp_incoming(); + if (commCheckUdpIncoming) + comm_select_udp_incoming(); - if (commCheckDNSIncoming) + if (commCheckDnsIncoming) comm_select_dns_incoming(); - if (commCheckHTTPIncoming) - comm_select_http_incoming(); + if (commCheckTcpIncoming) + comm_select_tcp_incoming(); } } } - if (callicp) - comm_select_icp_incoming(); + if (calludp) + comm_select_udp_incoming(); if (calldns) comm_select_dns_incoming(); - if (callhttp) - comm_select_http_incoming(); + if (calltcp) + comm_select_tcp_incoming(); getCurrentTime(); @@ -754,20 +779,20 @@ static void commIncomingStats(StoreEntry * sentry) { - storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n", - incoming_icp_interval >> INCOMING_FACTOR); + storeAppendPrintf(sentry, "Current incoming_udp_interval: %d\n", + incoming_udp_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n", incoming_dns_interval >> INCOMING_FACTOR); - storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n", - incoming_http_interval >> INCOMING_FACTOR); + storeAppendPrintf(sentry, "Current incoming_tcp_interval: %d\n", + incoming_tcp_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n"); - storeAppendPrintf(sentry, "ICP Messages handled per comm_select_icp_incoming() call:\n"); - statCounter.comm_icp_incoming.dump(sentry, statHistIntDumper); + storeAppendPrintf(sentry, "HTCP/ICP Messages handled per comm_select_udp_incoming() call:\n"); + statCounter.comm_udp_incoming.dump(sentry, statHistIntDumper); storeAppendPrintf(sentry, "DNS Messages handled per comm_select_dns_incoming() call:\n"); statCounter.comm_dns_incoming.dump(sentry, statHistIntDumper); - storeAppendPrintf(sentry, "HTTP Messages handled per comm_select_http_incoming() call:\n"); - statCounter.comm_http_incoming.dump(sentry, statHistIntDumper); + storeAppendPrintf(sentry, "HTTP/HTTPS Messages handled per comm_select_tcp_incoming() call:\n"); + statCounter.comm_tcp_incoming.dump(sentry, statHistIntDumper); } void === added file 'src/comm/UdpOpenDialer.h' --- src/comm/UdpOpenDialer.h 1970-01-01 00:00:00 +0000 +++ src/comm/UdpOpenDialer.h 2012-03-03 14:10:43 +0000 @@ -0,0 +1,29 @@ +#ifndef SQUID_COMM_UDPOPENDIALER_H +#define SQUID_COMM_UDPOPENDIALER_H + +#include "comm/Connection.h" +#include "ipc/StartListening.h" + +namespace Comm +{ + +/// dials a UDP port-opened call +class UdpOpenDialer: public CallDialer, + public Ipc::StartListeningCb +{ +public: + typedef void (*Handler)(const ConnectionPointer &conn, int errNo); + UdpOpenDialer(const ConnectionPointer &aConn, Handler aHandler): handler(aHandler), conn(aConn) {} + + virtual void print(std::ostream &os) const { startPrint(os) << ')'; } + virtual bool canDial(AsyncCall &) const { return true; } + virtual void dial(AsyncCall &) { (handler)(conn, errNo); } + +public: + Handler handler; + const ConnectionPointer conn; +}; + +} // namespace Comm + +#endif /* SQUID_COMM_UDPOPENDIALER_H */ === modified file 'src/defines.h' --- src/defines.h 2011-08-26 16:50:49 +0000 +++ src/defines.h 2012-03-04 02:36:54 +0000 @@ -209,33 +209,6 @@ #define countof(arr) (sizeof(arr)/sizeof(*arr)) /* - * Max number of ICP messages to receive per call to icpHandleUdp - */ -#if _SQUID_MSWIN_ -#define INCOMING_ICP_MAX 1 -#else -#define INCOMING_ICP_MAX 15 -#endif -/* - * Max number of DNS messages to receive per call to DNS read handler - */ -#if _SQUID_MSWIN_ -#define INCOMING_DNS_MAX 1 -#else -#define INCOMING_DNS_MAX 15 -#endif -/* - * Max number of HTTP connections to accept per call to httpAccept - * and PER HTTP PORT - */ -#if _SQUID_MSWIN_ -#define INCOMING_HTTP_MAX 1 -#else -#define INCOMING_HTTP_MAX 10 -#endif -#define INCOMING_TOTAL_MAX (INCOMING_ICP_MAX+INCOMING_HTTP_MAX) - -/* * This many TCP connections must FAIL before we mark the * peer as DEAD */ === modified file 'src/dns_internal.cc' --- src/dns_internal.cc 2012-03-05 11:36:38 +0000 +++ src/dns_internal.cc 2012-03-06 22:42:52 +0000 @@ -842,10 +842,10 @@ Comm::ConnectionPointer conn = new Comm::Connection(); - if (!Config.Addrs.udp_outgoing.IsNoAddr()) - conn->local = Config.Addrs.udp_outgoing; + if (!Config.dns.outgoingAddr.IsNoAddr()) + conn->local = Config.dns.outgoingAddr; else - conn->local = Config.Addrs.udp_incoming; + conn->local = Config.dns.incomingAddr; conn->remote = nameservers[ns].S; @@ -1480,10 +1480,10 @@ if (DnsSocketA < 0 && DnsSocketB < 0) { Ip::Address addrV6; // since we don't want to alter Config.Addrs.udp_* and dont have one of our own. - if (!Config.Addrs.udp_outgoing.IsNoAddr()) - addrV6 = Config.Addrs.udp_outgoing; + if (!Config.dns.outgoingAddr.IsNoAddr()) + addrV6 = Config.dns.outgoingAddr; else - addrV6 = Config.Addrs.udp_incoming; + addrV6 = Config.dns.incomingAddr; Ip::Address addrV4 = addrV6; addrV4.SetIPv4(); @@ -1639,6 +1639,8 @@ idns_query *q = cbdataAlloc(idns_query); memcpy(q->name, master->name, sizeof(q->name)); memcpy(q->orig, master->orig, sizeof(q->orig)); + q->callback = NULL; + q->callback_data = NULL; q->master = master; q->query_id = idnsQueryID(); q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, Config.dns.packet_max); === modified file 'src/htcp.cc' --- src/htcp.cc 2012-01-20 18:55:04 +0000 +++ src/htcp.cc 2012-03-06 12:44:07 +0000 @@ -39,11 +39,11 @@ #include "acl/Acl.h" #include "comm.h" #include "comm/Loops.h" +#include "comm/UdpOpenDialer.h" #include "htcp.h" #include "http.h" #include "HttpRequest.h" #include "icmp/net_db.h" -#include "ipc/StartListening.h" #include "ip/tools.h" #include "MemBuf.h" #include "SquidTime.h" @@ -52,22 +52,6 @@ #include "StoreClient.h" #include "compat/xalloc.h" -/// dials htcpIncomingConnectionOpened call -class HtcpListeningStartedDialer: public CallDialer, - public Ipc::StartListeningCb -{ -public: - typedef void (*Handler)(int errNo); - HtcpListeningStartedDialer(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)(errNo); } - -public: - Handler handler; -}; - typedef struct _Countstr Countstr; typedef struct _htcpHeader htcpHeader; @@ -246,11 +230,9 @@ RR_RESPONSE }; -static void htcpIncomingConnectionOpened(int errNo); +static void htcpPortOpened(const Comm::ConnectionPointer &conn, int errNo); static uint32_t msg_id_counter = 0; -static Comm::ConnectionPointer htcpOutgoingConn = NULL; -static Comm::ConnectionPointer htcpIncomingConn = NULL; #define N_QUERIED_KEYS 8192 static uint32_t queried_id[N_QUERIED_KEYS]; static cache_key queried_keys[N_QUERIED_KEYS][SQUID_MD5_DIGEST_LENGTH]; @@ -259,7 +241,7 @@ static MemAllocator *htcpDetailPool = NULL; static int old_squid_format = 0; - +bool htcpActive = false; static ssize_t htcpBuildPacket(char *buf, size_t buflen, htcpStuff * stuff); static htcpSpecifier *htcpUnpackSpecifier(char *buf, int sz); @@ -287,7 +269,7 @@ static void htcpRecv(int fd, void *data); -static void htcpSend(const char *buf, int len, Ip::Address &to); +static void htcpSend(const Comm::ConnectionPointer &htcpOutgoingConn, const char *buf, int len, Ip::Address &to); static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, Ip::Address &); @@ -615,7 +597,7 @@ } static void -htcpSend(const char *buf, int len, Ip::Address &to) +htcpSend(const Comm::ConnectionPointer &htcpOutgoingConn, const char *buf, int len, Ip::Address &to) { debugs(31, 3, HERE << to); htcpHexdump("htcpSend", buf, len); @@ -863,6 +845,20 @@ return (checklist.fastCheck() == ACCESS_ALLOWED); } +/// Locate an open HTCP port which can use for packets to the given destination +static Comm::ConnectionPointer +htcpLocateOutConn(const Ip::Address &sendingTo) +{ + // NP: we simplify the split-stack/dual-stack port management by just going split-stack + // even on systems where one port would have been fine. + for (AnyP::PortList *s = Config.Sockaddr.htcp; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn) && sendingTo.IsIPv4() == s->s.IsIPv4()) { + return s->listenConn; + } + } + return Comm::ConnectionPointer(); +} + static void htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, Ip::Address &from) { @@ -880,6 +876,10 @@ debugs(31, 3, "htcpTstReply: response = " << stuff.response); stuff.msg_id = dhdr->msg_id; + const Comm::ConnectionPointer htcpOutgoingConn = htcpLocateOutConn(from); + if (htcpOutgoingConn == NULL) + return; + if (spec) { mb.init(); packerToMemInit(&p, &mb); @@ -948,7 +948,7 @@ return; } - htcpSend(pkt, (int) pktlen, from); + htcpSend(htcpOutgoingConn, pkt, (int) pktlen, from); } static void @@ -964,6 +964,10 @@ if (dhdr->F1 == 0) return; + const Comm::ConnectionPointer htcpOutgoingConn = htcpLocateOutConn(from); + if (htcpOutgoingConn == NULL) + return; + memset(&stuff, '\0', sizeof(stuff)); stuff.op = HTCP_CLR; @@ -985,7 +989,7 @@ return; } - htcpSend(pkt, (int) pktlen, from); + htcpSend(htcpOutgoingConn, pkt, (int) pktlen, from); } static void @@ -1329,7 +1333,11 @@ continue; } - htcpSend(buf, sz, p->in_addr); + const Comm::ConnectionPointer htcpOutgoingConn = htcpLocateOutConn(p->in_addr); + if (htcpOutgoingConn == NULL) + continue; + + htcpSend(htcpOutgoingConn, buf, sz, p->in_addr); } } @@ -1485,59 +1493,24 @@ */ void -htcpInit(void) +htcpOpenPorts(void) { - if (Config.Port.htcp <= 0) { + if (!Config.Sockaddr.htcp) { debugs(31, DBG_IMPORTANT, "HTCP Disabled."); return; } - htcpIncomingConn = new Comm::Connection; - htcpIncomingConn->local = Config.Addrs.udp_incoming; - htcpIncomingConn->local.SetPort(Config.Port.htcp); - - if (!Ip::EnableIpv6 && !htcpIncomingConn->local.SetIPv4()) { - debugs(31, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << htcpIncomingConn->local << " is not an IPv4 address."); - fatal("HTCP port cannot be opened."); - } - /* split-stack for now requires default IPv4-only HTCP */ - if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && htcpIncomingConn->local.IsAnyAddr()) { - htcpIncomingConn->local.SetIPv4(); - } - - AsyncCall::Pointer call = asyncCall(31, 2, - "htcpIncomingConnectionOpened", - HtcpListeningStartedDialer(&htcpIncomingConnectionOpened)); - - Ipc::StartListening(SOCK_DGRAM, - IPPROTO_UDP, - htcpIncomingConn, - Ipc::fdnInHtcpSocket, call); - - if (!Config.Addrs.udp_outgoing.IsNoAddr()) { - htcpOutgoingConn = new Comm::Connection; - htcpOutgoingConn->local = Config.Addrs.udp_outgoing; - htcpOutgoingConn->local.SetPort(Config.Port.htcp); - - if (!Ip::EnableIpv6 && !htcpOutgoingConn->local.SetIPv4()) { - debugs(31, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << htcpOutgoingConn->local << " is not an IPv4 address."); - fatal("HTCP port cannot be opened."); - } - /* split-stack for now requires default IPv4-only HTCP */ - if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && htcpOutgoingConn->local.IsAnyAddr()) { - htcpOutgoingConn->local.SetIPv4(); - } - - enter_suid(); - comm_open_listener(SOCK_DGRAM, IPPROTO_UDP, htcpOutgoingConn, "Outgoing HTCP Socket"); - leave_suid(); - - if (!Comm::IsConnOpen(htcpOutgoingConn)) - fatal("Cannot open Outgoing HTCP Socket"); - - Comm::SetSelect(htcpOutgoingConn->fd, COMM_SELECT_READ, htcpRecv, NULL, 0); - - debugs(31, DBG_IMPORTANT, "Sending HTCP messages from " << htcpOutgoingConn->local); + for (AnyP::PortList *s = Config.Sockaddr.htcp; s; s = s->next) { + s->listenConn = new Comm::Connection; + + AsyncCall::Pointer call = asyncCall(31, 2, + "htcpPortOpened", + Comm::UdpOpenDialer(s->listenConn, &htcpPortOpened)); + + Ipc::StartListening(SOCK_DGRAM, + IPPROTO_UDP, + s->listenConn, + Ipc::fdnInHtcpSocket, call); } if (!htcpDetailPool) { @@ -1546,24 +1519,26 @@ } static void -htcpIncomingConnectionOpened(int) +htcpPortOpened(const Comm::ConnectionPointer &conn, int) { - if (!Comm::IsConnOpen(htcpIncomingConn)) - fatal("Cannot open HTCP Socket"); - - Comm::SetSelect(htcpIncomingConn->fd, COMM_SELECT_READ, htcpRecv, NULL, 0); - - debugs(31, DBG_CRITICAL, "Accepting HTCP messages on " << htcpIncomingConn->local); - - if (Config.Addrs.udp_outgoing.IsNoAddr()) { - htcpOutgoingConn = htcpIncomingConn; - debugs(31, DBG_IMPORTANT, "Sending HTCP messages from " << htcpOutgoingConn->local); - } + if (Comm::IsConnOpen(conn)) { + Comm::SetSelect(conn->fd, COMM_SELECT_READ, htcpRecv, NULL, 0); + debugs(31, DBG_CRITICAL, "Accepting HTCP messages on " << conn->local); + fd_note(conn->fd, "HTCP Port"); + htcpActive = true; + } else + debugs(31, DBG_CRITICAL, "ERROR: Cannot open HTCP port " << conn->local); } int htcpQuery(StoreEntry * e, HttpRequest * req, peer * p) { + const Comm::ConnectionPointer htcpOutgoingConn = htcpLocateOutConn(p->in_addr); + if (htcpOutgoingConn == NULL) { + debugs(15, DBG_CRITICAL, "HTCP is disabled! Cannot send HTCP request to peer."); + return 0; + } + cache_key *save_key; static char pkt[8192]; ssize_t pktlen; @@ -1574,9 +1549,6 @@ MemBuf mb; http_state_flags flags; - if (!Comm::IsConnOpen(htcpIncomingConn)) - return 0; - old_squid_format = p->options.htcp_oldsquid; memset(&flags, '\0', sizeof(flags)); snprintf(vbuf, sizeof(vbuf), "%d/%d", @@ -1603,7 +1575,7 @@ return -1; } - htcpSend(pkt, (int) pktlen, p->in_addr); + htcpSend(htcpOutgoingConn, pkt, (int) pktlen, p->in_addr); queried_id[stuff.msg_id % N_QUERIED_KEYS] = stuff.msg_id; save_key = queried_keys[stuff.msg_id % N_QUERIED_KEYS]; @@ -1629,7 +1601,8 @@ MemBuf mb; http_state_flags flags; - if (!Comm::IsConnOpen(htcpIncomingConn)) + const Comm::ConnectionPointer htcpOutgoingConn = htcpLocateOutConn(p->in_addr); + if (htcpOutgoingConn == NULL) return; old_squid_format = p->options.htcp_oldsquid; @@ -1682,51 +1655,24 @@ return; } - htcpSend(pkt, (int) pktlen, p->in_addr); + htcpSend(htcpOutgoingConn, pkt, (int) pktlen, p->in_addr); } -/* - * htcpSocketShutdown only closes the 'in' socket if it is - * different than the 'out' socket. +/** + * Close all HTCP ports. + * This terminates all HTCP traffic. */ void -htcpSocketShutdown(void) -{ - if (!Comm::IsConnOpen(htcpIncomingConn)) - return; - - debugs(12, DBG_IMPORTANT, "Stop accepting HTCP on " << htcpIncomingConn->local); - /* - * Here we just unlink htcpIncomingConn because the HTCP 'in' - * and 'out' sockets might be just one FD. This prevents this - * function from executing repeatedly. When we are really ready to - * exit or restart, main will comm_close the 'out' descriptor. - */ - htcpIncomingConn = NULL; - - /* - * Normally we only write to the outgoing HTCP socket, but - * we also have a read handler there to catch messages sent - * to that specific interface. During shutdown, we must - * disable reading on the outgoing socket. - */ - /* XXX Don't we need this handler to read replies while shutting down? - * I think there should be a separate hander for reading replies.. - */ - assert(Comm::IsConnOpen(htcpOutgoingConn)); - - Comm::SetSelect(htcpOutgoingConn->fd, COMM_SELECT_READ, NULL, NULL, 0); -} - -void -htcpSocketClose(void) -{ - htcpSocketShutdown(); - - if (htcpOutgoingConn != NULL) { - debugs(12, DBG_IMPORTANT, "Stop sending HTCP from " << htcpOutgoingConn->local); - htcpOutgoingConn = NULL; +htcpClosePorts(void) +{ + for (AnyP::PortList *s = Config.Sockaddr.htcp; s; s = s->next) { + if (!Comm::IsConnOpen(s->listenConn)) + continue; + + s->listenConn->close(); + debugs(12, DBG_IMPORTANT, "Stop accepting HTCP on " << s->listenConn->local); } + htcpActive = false; } static void === modified file 'src/htcp.h' --- src/htcp.h 2010-07-06 12:44:06 +0000 +++ src/htcp.h 2012-03-09 01:11:42 +0000 @@ -55,6 +55,9 @@ } cto; }; +/// whether any HTCP ports are currently open +extern bool htcpActive; + /// \bug redundant typedef typedef class HtcpReplyData htcpReplyData; @@ -62,7 +65,7 @@ SQUIDCEXTERN void neighborsHtcpReply(const cache_key *, htcpReplyData *, const Ip::Address &); /// \ingroup ServerProtocolHTCP -SQUIDCEXTERN void htcpInit(void); +SQUIDCEXTERN void htcpOpenPorts(void); /** * \ingroup ServerProtocolHTCP @@ -83,10 +86,7 @@ SQUIDCEXTERN void htcpClear(StoreEntry * e, const char *uri, HttpRequest * req, const HttpRequestMethod &method, peer * p, htcp_clr_reason reason); /// \ingroup ServerProtocolHTCP -SQUIDCEXTERN void htcpSocketShutdown(void); - -/// \ingroup ServerProtocolHTCP -SQUIDCEXTERN void htcpSocketClose(void); +SQUIDCEXTERN void htcpClosePorts(void); #endif /* USE_HTCP */ === modified file 'src/icp_v2.cc' --- src/icp_v2.cc 2012-01-20 18:55:04 +0000 +++ src/icp_v2.cc 2012-03-06 23:55:08 +0000 @@ -41,6 +41,7 @@ #include "comm/Loops.h" #include "ICP.h" #include "comm/Connection.h" +#include "comm/UdpOpenDialer.h" #include "HttpRequest.h" #include "acl/FilledChecklist.h" #include "acl/Acl.h" @@ -52,28 +53,10 @@ #include "icmp/net_db.h" #include "ip/Address.h" #include "ip/tools.h" -#include "ipc/StartListening.h" #include "ipcache.h" #include "rfc1738.h" -/// dials icpIncomingConnectionOpened call -class IcpListeningStartedDialer: public CallDialer, - public Ipc::StartListeningCb -{ -public: - typedef void (*Handler)(int errNo); - IcpListeningStartedDialer(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)(errNo); } - -public: - Handler handler; -}; - -static void icpIncomingConnectionOpened(int errNo); +static void icpPortOpened(const Comm::ConnectionPointer &conn, int errNo); /// \ingroup ServerProtocolICPInternal2 static void icpLogIcp(const Ip::Address &, log_type, int, const char *, int); @@ -92,11 +75,8 @@ static icpUdpData *IcpQueueHead = NULL; /// \ingroup ServerProtocolICPInternal2 static icpUdpData *IcpQueueTail = NULL; +bool icpActive = false; -/// \ingroup ServerProtocolICPInternal2 -Comm::ConnectionPointer icpIncomingConn = NULL; -/// \ingroup ServerProtocolICPInternal2 -Comm::ConnectionPointer icpOutgoingConn = NULL; /* icp_common_t */ _icp_common_t::_icp_common_t() : opcode(ICP_INVALID), version(0), length(0), reqnum(0), flags(0), pad(0), shostid(0) @@ -240,7 +220,7 @@ while ((q = IcpQueueHead) != NULL) { int delay = tvSubUsec(q->queue_time, current_time); /* increment delay to prevent looping */ - const int x = icpUdpSend(fd, q->address, (icp_common_t *) q->msg, q->logcode, ++delay); + const int x = icpUdpSend(q->peerDetail, q->address, (icp_common_t *) q->msg, q->logcode, ++delay); IcpQueueHead = q->next; xfree(q); @@ -294,31 +274,48 @@ return (icp_common_t *)buf; } +Comm::ConnectionPointer +icpLocateOutConn(const Ip::Address &sendingTo) +{ + // NP: we simplify the split-stack/dual-stack port management by just going split-stack + // even on systems where one port would have been fine. + for (AnyP::PortList *s = Config.Sockaddr.icp; s; s = s->next) { + if (Comm::IsConnOpen(s->listenConn) && sendingTo.IsIPv4() == s->s.IsIPv4()) { + return s->listenConn; + } + } + return Comm::ConnectionPointer(); +} + int -icpUdpSend(int fd, - const Ip::Address &to, - icp_common_t * msg, - log_type logcode, - int delay) +icpUdpSend(const peer *p, const Ip::Address &from, icp_common_t * msg, log_type logcode, int delay) { + const Comm::ConnectionPointer icpOutConn = icpLocateOutConn(p?p->in_addr:from); + if (icpOutConn == NULL) + return 0; + icpUdpData *queue; int x; int len; len = (int) ntohs(msg->length); - debugs(12, 5, "icpUdpSend: FD " << fd << " sending " << - icp_opcode_str[msg->opcode] << ", " << len << " bytes to " << to); - - x = comm_udp_sendto(fd, to, msg, len); + debugs(12, 5, HERE << "FD " << icpOutConn->fd << ", " << icpOutConn->local << " sending " << + icp_opcode_str[msg->opcode] << ", " << len << " bytes to " << (p?p->in_addr:from)); + + if (p && p->type == PEER_MULTICAST) + mcastSetTtl(icpOutConn->fd, p->mcast.ttl); + + x = comm_udp_sendto(icpOutConn->fd, (p?p->in_addr:from), msg, len); if (x >= 0) { /* successfully written */ - icpLogIcp(to, logcode, len, (char *) (msg + 1), delay); + icpLogIcp((p?p->in_addr:from), logcode, len, (char *) (msg + 1), delay); icpCount(msg, SENT, (size_t) len, delay); safe_free(msg); } else if (0 == delay) { /* send failed, but queue it */ queue = (icpUdpData *) xcalloc(1, sizeof(icpUdpData)); - queue->address = to; + queue->peerDetail = p; + queue->address = (p?p->in_addr:from); queue->msg = msg; queue->len = (int) ntohs(msg->length); queue->queue_time = current_time; @@ -335,7 +332,7 @@ IcpQueueTail = queue; } - Comm::SetSelect(fd, COMM_SELECT_WRITE, icpUdpSendQueue, NULL, 0); + Comm::SetSelect(icpOutConn->fd, COMM_SELECT_WRITE, icpUdpSendQueue, NULL, 0); statCounter.icp.replies_queued++; } else { /* don't queue it */ @@ -409,7 +406,8 @@ icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from) { icp_common_t *reply = _icp_common_t::createMessage(opcode, flags, url, reqnum, pad); - icpUdpSend(fd, from, reply, icpLogFromICPCode(opcode), 0); + + icpUdpSend((peer *)NULL, from, reply, icpLogFromICPCode(opcode), 0); } void @@ -612,7 +610,7 @@ LOCAL_ARRAY(char, buf, SQUID_UDP_SO_RCVBUF); int len; int icp_version; - int max = INCOMING_ICP_MAX; + int max = INCOMING_UDP_MAX; Comm::SetSelect(sock, COMM_SELECT_READ, icpHandleUdp, NULL, 0); while (max--) { @@ -660,9 +658,14 @@ icp_version = (int) buf[1]; /* cheat! */ - if (icpOutgoingConn->local == from) + // TODO: find a faster way to ignore packets that we sent + bool ourPacket = false; + for (const AnyP::PortList *s = Config.Sockaddr.icp; s && !ourPacket; s=s->next) + ourPacket = (s->listenConn->local == from); + + if (ourPacket) // ignore ICP packets which loop back (multicast usually) - debugs(12, 4, "icpHandleUdp: Ignoring UDP packet sent by myself"); + debugs(12, 4, HERE << "Ignoring ICP packet sent by myself"); else if (icp_version == ICP_VERSION_2) icpHandleIcpV2(sock, from, buf, len); else if (icp_version == ICP_VERSION_3) @@ -674,122 +677,59 @@ } void -icpConnectionsOpen(void) +icpOpenPorts(void) { - uint16_t port; - - if ((port = Config.Port.icp) <= 0) + if (!Config.Sockaddr.icp) { + debugs(31, DBG_IMPORTANT, "ICP Disabled."); return; - - icpIncomingConn = new Comm::Connection; - icpIncomingConn->local = Config.Addrs.udp_incoming; - icpIncomingConn->local.SetPort(port); - - if (!Ip::EnableIpv6 && !icpIncomingConn->local.SetIPv4()) { - debugs(12, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << icpIncomingConn->local << " is not an IPv4 address."); - fatal("ICP port cannot be opened."); - } - /* split-stack for now requires default IPv4-only ICP */ - if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpIncomingConn->local.IsAnyAddr()) { - icpIncomingConn->local.SetIPv4(); - } - - AsyncCall::Pointer call = asyncCall(12, 2, - "icpIncomingConnectionOpened", - IcpListeningStartedDialer(&icpIncomingConnectionOpened)); - - Ipc::StartListening(SOCK_DGRAM, - IPPROTO_UDP, - icpIncomingConn, - Ipc::fdnInIcpSocket, call); - - if ( !Config.Addrs.udp_outgoing.IsNoAddr() ) { - icpOutgoingConn = new Comm::Connection; - icpOutgoingConn->local = Config.Addrs.udp_outgoing; - icpOutgoingConn->local.SetPort(port); - - if (!Ip::EnableIpv6 && !icpOutgoingConn->local.SetIPv4()) { - debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << icpOutgoingConn->local << " is not an IPv4 address."); - fatal("ICP port cannot be opened."); - } - /* split-stack for now requires default IPv4-only ICP */ - if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpOutgoingConn->local.IsAnyAddr()) { - icpOutgoingConn->local.SetIPv4(); - } - - enter_suid(); - comm_open_listener(SOCK_DGRAM, IPPROTO_UDP, icpOutgoingConn, "Outgoing ICP Port"); - leave_suid(); - - if (!Comm::IsConnOpen(icpOutgoingConn)) - fatal("Cannot open Outgoing ICP Port"); - - debugs(12, DBG_CRITICAL, "Sending ICP messages from " << icpOutgoingConn->local); - - Comm::SetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0); - fd_note(icpOutgoingConn->fd, "Outgoing ICP socket"); + } + + for (AnyP::PortList *s = Config.Sockaddr.icp; s; s = s->next) { + s->listenConn = new Comm::Connection; + + AsyncCall::Pointer call = asyncCall(12, 2, + "icpPortOpened", + Comm::UdpOpenDialer(s->listenConn,&icpPortOpened)); + + Ipc::StartListening(SOCK_DGRAM, + IPPROTO_UDP, + s->listenConn, + Ipc::fdnInIcpSocket, call); } } static void -icpIncomingConnectionOpened(int errNo) +icpPortOpened(const Comm::ConnectionPointer &conn, int errNo) { - if (!Comm::IsConnOpen(icpIncomingConn)) - fatal("Cannot open ICP Port"); - - Comm::SetSelect(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); // XXX: pass the icpIncomingConn for mcastJoinGroups usage. - - debugs(12, DBG_IMPORTANT, "Accepting ICP messages on " << icpIncomingConn->local); - - fd_note(icpIncomingConn->fd, "Incoming ICP port"); - - if (Config.Addrs.udp_outgoing.IsNoAddr()) { - icpOutgoingConn = icpIncomingConn; - debugs(12, DBG_IMPORTANT, "Sending ICP messages from " << icpOutgoingConn->local); - } + if (Comm::IsConnOpen(conn)) { + Comm::SetSelect(conn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0); + for (const wordlist *s = Config.mcast_group_list; s; s = s->next) { + // XXX: yuck. we need a better way to do this. + Comm::ConnectionPointer *tmp = new Comm::ConnectionPointer(conn); + ipcache_nbgethostbyname(s->key, mcastJoinGroups, new generic_cbdata(tmp)); + } + debugs(12, DBG_IMPORTANT, "Accepting ICP messages on " << conn->local); + fd_note(conn->fd, "ICP port"); + icpActive = true; + } else + debugs(12, DBG_CRITICAL, "ERROR: Cannot open ICP port " << conn->local); } /** - * icpConnectionShutdown only closes the 'in' socket if it is - * different than the 'out' socket. + * Close all ICP ports. + * This terminates all ICP traffic. */ void -icpConnectionShutdown(void) -{ - if (!Comm::IsConnOpen(icpIncomingConn)) - return; - - debugs(12, DBG_IMPORTANT, "Stop receiving ICP on " << icpIncomingConn->local); - - /** Release the 'in' socket for lazy closure. - * in and out sockets may be sharing one same FD. - * This prevents this function from executing repeatedly. - */ - icpIncomingConn = NULL; - - /** - * Normally we only write to the outgoing ICP socket, but - * we also have a read handler there to catch messages sent - * to that specific interface. During shutdown, we must - * disable reading on the outgoing socket. - */ - assert(Comm::IsConnOpen(icpOutgoingConn)); - - Comm::SetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, NULL, NULL, 0); -} - -void -icpConnectionClose(void) -{ - icpConnectionShutdown(); - - if (icpOutgoingConn != NULL) { - debugs(12, DBG_IMPORTANT, "Stop sending ICP from " << icpOutgoingConn->local); - icpOutgoingConn = NULL; +icpClosePorts(void) +{ + for (AnyP::PortList *s = Config.Sockaddr.icp; s; s = s->next) { + if (!Comm::IsConnOpen(s->listenConn)) + continue; + + s->listenConn->close(); + debugs(12, DBG_IMPORTANT, "Stop accepting ICP on " << s->listenConn->local); } + icpActive = false; } static void === modified file 'src/main.cc' --- src/main.cc 2012-01-27 13:41:01 +0000 +++ src/main.cc 2012-03-09 01:05:09 +0000 @@ -139,7 +139,6 @@ #endif static char *opt_syslog_facility = NULL; -static int icpPortNumOverride = 1; /* Want to detect "-u 0" */ static int configured_once = 0; #if MALLOC_DBG static int malloc_debug_level = 0; @@ -393,7 +392,7 @@ case 'a': /** \par a * Add optional HTTP port as given following the option */ - add_http_port(optarg); + add_generic_port(optarg,"http"); break; case 'd': @@ -532,13 +531,8 @@ case 'u': /** \par u - * Store the ICP port number given in global option icpPortNumOverride - * ensuring its a positive number. */ - icpPortNumOverride = atoi(optarg); - - if (icpPortNumOverride < 0) - icpPortNumOverride = 0; - + * Add optional ICP port as given following the option */ + add_generic_port(optarg,"icp"); break; case 'v': @@ -667,13 +661,12 @@ // start various proxying services if we are responsible for them if (IamWorkerProcess()) { clientOpenListenSockets(); - icpConnectionsOpen(); + icpOpenPorts(); #if USE_HTCP - - htcpInit(); + htcpOpenPorts(); #endif #if SQUID_SNMP - snmpConnectionOpen(); + snmpOpenPorts(); #endif clientdbInit(); @@ -708,15 +701,14 @@ } if (IamWorkerProcess()) { clientHttpConnectionsClose(); - icpConnectionShutdown(); + icpClosePorts(); #if USE_HTCP - - htcpSocketShutdown(); + htcpClosePorts(); #endif icmpEngine.Close(); #if SQUID_SNMP - snmpConnectionClose(); + snmpClosePorts(); #endif asnFreeMemory(); @@ -731,10 +723,9 @@ // Initiate asynchronous closing sequence serverConnectionsClose(); - icpConnectionClose(); + icpClosePorts(); #if USE_HTCP - - htcpSocketClose(); + htcpClosePorts(); #endif dnsShutdown(); #if USE_SSL_CRTD @@ -964,9 +955,6 @@ setEffectiveUser(); - if (icpPortNumOverride != 1) - Config.Port.icp = (unsigned short) icpPortNumOverride; - _db_init(Debug::cache_log, Debug::debugOptions); fd_open(fileno(debug_log), FD_LOG, Debug::cache_log); @@ -1832,13 +1820,12 @@ #endif redirectShutdown(); externalAclShutdown(); - icpConnectionClose(); + icpClosePorts(); #if USE_HTCP - - htcpSocketClose(); + htcpClosePorts(); #endif #if SQUID_SNMP - snmpConnectionClose(); + snmpClosePorts(); #endif #if USE_WCCP === modified file 'src/multicast.cc' --- src/multicast.cc 2012-01-20 18:55:04 +0000 +++ src/multicast.cc 2012-03-04 11:14:32 +0000 @@ -54,14 +54,20 @@ } void -mcastJoinGroups(const ipcache_addrs *ia, const DnsLookupDetails &, void *datanotused) +mcastJoinGroups(const ipcache_addrs *ia, const DnsLookupDetails &, void *data) { #ifdef IP_MULTICAST_TTL + // XXX: yuck. when we have a UDP receiver Job that will be the data. + generic_cbdata *d = static_cast(data); + Comm::ConnectionPointer *conn; + d->unwrap(&conn); // deletes itself + struct ip_mreq mr; int i; if (ia == NULL) { debugs(7, 0, "comm_join_mcast_groups: Unknown host"); + delete conn; return; } @@ -77,13 +83,13 @@ mr.imr_interface.s_addr = INADDR_ANY; - 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 (setsockopt((*conn)->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mr, sizeof(struct ip_mreq)) < 0) + debugs(7, DBG_IMPORTANT, "ERROR: Join failed for " << (*conn)->local << ", Multicast IP=" << ia->in_addrs[i]); 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()); + if (setsockopt((*conn)->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1) < 0) + debugs(7, DBG_IMPORTANT, "ERROR: " << (*conn)->local << " can't disable multicast loopback: " << xstrerror()); } - + delete conn; #endif } === modified file 'src/neighbors.cc' --- src/neighbors.cc 2012-01-20 18:55:04 +0000 +++ src/neighbors.cc 2012-03-05 10:58:58 +0000 @@ -31,8 +31,8 @@ */ #include "squid-old.h" -#include "ProtoPort.h" #include "acl/FilledChecklist.h" +#include "anyp/PortList.h" #include "comm/Connection.h" #include "comm/ConnOpener.h" #include "event.h" @@ -520,7 +520,11 @@ "Peer Cache Statistics", neighborDumpPeers, 0, 1); - if (Comm::IsConnOpen(icpIncomingConn)) { +#if USE_HTCP + if (htcpActive || icpActive) { +#else + if (icpActive) { +#endif Mgr::RegisterAction("non_peers", "List of Unknown sites sending ICP messages", neighborDumpNonPeers, 0, 1); @@ -537,16 +541,19 @@ neighborsRegisterWithCacheManager(); - if (Comm::IsConnOpen(icpIncomingConn)) { +#if USE_HTCP + if (htcpActive || icpActive) { +#else + if (icpActive) { +#endif for (thisPeer = Config.peers; thisPeer; thisPeer = next) { - http_port_list *s = NULL; next = thisPeer->next; if (0 != strcmp(thisPeer->host, me)) continue; - for (s = Config.Sockaddr.http; s; s = s->next) { + for (AnyP::PortList *s = Config.Sockaddr.http; s; s = s->next) { if (thisPeer->http_port != s->s.GetPort()) continue; @@ -623,28 +630,22 @@ #if USE_HTCP if (p->options.htcp && !p->options.htcp_only_clr) { - if (Config.Port.htcp <= 0) { - debugs(15, DBG_CRITICAL, "HTCP is disabled! Cannot send HTCP request to peer."); - continue; - } - debugs(15, 3, "neighborsUdpPing: sending HTCP query"); - if (htcpQuery(entry, request, p) <= 0) continue; // unable to send. + if (htcpQuery(entry, request, p) <= 0) + continue; // unable to send. } else #endif { - if (Config.Port.icp <= 0 || !Comm::IsConnOpen(icpOutgoingConn)) { + if (!icpActive) { debugs(15, DBG_CRITICAL, "ICP is disabled! Cannot send ICP request to peer."); continue; } else { - if (p->type == PEER_MULTICAST) - mcastSetTtl(icpOutgoingConn->fd, p->mcast.ttl); - if (p->icp.port == echo_port) { debugs(15, 4, "neighborsUdpPing: Looks like a dumb cache, send DECHO ping"); query = _icp_common_t::createMessage(ICP_DECHO, 0, url, reqnum, 0); - icpUdpSend(icpOutgoingConn->fd, p->in_addr, query, LOG_ICP_QUERY, 0); + if (icpUdpSend(p, p->in_addr, query, LOG_ICP_QUERY, 0) <= 0) + continue; // unable to send. } else { flags = 0; @@ -654,7 +655,8 @@ query = _icp_common_t::createMessage(ICP_QUERY, flags, url, reqnum, 0); - icpUdpSend(icpOutgoingConn->fd, p->in_addr, query, LOG_ICP_QUERY, 0); + if (icpUdpSend(p, p->in_addr, query, LOG_ICP_QUERY, 0) <= 0) + continue; // unable to send. } } } @@ -1388,11 +1390,10 @@ mem->start_ping = current_time; mem->ping_reply_callback = peerCountHandleIcpReply; mem->ircb_data = psstate; - mcastSetTtl(icpOutgoingConn->fd, p->mcast.ttl); p->mcast.id = mem->id; reqnum = icpSetCacheKey((const cache_key *)fake->key); query = _icp_common_t::createMessage(ICP_QUERY, 0, url, reqnum, 0); - icpUdpSend(icpOutgoingConn->fd, p->in_addr, query, LOG_ICP_QUERY, 0); + icpUdpSend(p, p->in_addr, query, LOG_ICP_QUERY, 0); fake->ping_status = PING_WAITING; eventAdd("peerCountMcastPeersDone", peerCountMcastPeersDone, === modified file 'src/protos.h' --- src/protos.h 2012-01-03 02:19:30 +0000 +++ src/protos.h 2012-03-06 13:25:05 +0000 @@ -66,7 +66,7 @@ class MemBuf; SQUIDCEXTERN void wordlistCat(const wordlist *, MemBuf * mb); SQUIDCEXTERN void self_destruct(void); -SQUIDCEXTERN void add_http_port(char *portspec); +SQUIDCEXTERN void add_generic_port(char *portspec, const char *protocol); extern int xatoi(const char *token); extern long xatol(const char *token); @@ -239,8 +239,8 @@ #if SQUID_SNMP SQUIDCEXTERN PF snmpHandleUdp; SQUIDCEXTERN void snmpInit(void); -SQUIDCEXTERN void snmpConnectionOpen(void); -SQUIDCEXTERN void snmpConnectionClose(void); +SQUIDCEXTERN void snmpOpenPorts(void); +SQUIDCEXTERN void snmpClosePorts(void); SQUIDCEXTERN const char * snmpDebugOid(oid * Name, snint Len, MemBuf &outbuf); SQUIDCEXTERN void addr2oid(Ip::Address &addr, oid *Dest); === modified file 'src/send-announce.cc' --- src/send-announce.cc 2012-01-20 18:55:04 +0000 +++ src/send-announce.cc 2012-03-05 12:23:18 +0000 @@ -34,6 +34,7 @@ */ #include "squid-old.h" +#include "anyp/PortList.h" #include "comm/Connection.h" #include "event.h" #include "fde.h" @@ -46,10 +47,7 @@ void start_announce(void *datanotused) { - if (0 == Config.onoff.announce) - return; - - if (!Comm::IsConnOpen(icpOutgoingConn)) + if (!Config.onoff.announce || !icpActive) return; ipcache_nbgethostbyname(Config.Announce.host, send_announce, NULL); @@ -75,15 +73,29 @@ return; } - debugs(27, 1, "Sending Announcement to " << host); + // XXX: re-work this send functionality to support + // - multiple IP results, + // - multiple multiple listening ports + // - multiple multiple transport types on listening ports + // - multiple multiple and non-ICP probe ports + // Does IRcache announce need the whole matrix for backward compatibility or can we alter/extend the lines here freely? + Ip::Address S = ia->in_addrs[0]; + S.SetPort(port); + + debugs(27, DBG_IMPORTANT, "Sending Announcement to " << host); sndbuf[0] = '\0'; snprintf(tbuf, 256, "cache_version SQUID/%s\n", version_string); strcat(sndbuf, tbuf); - assert(Config.Sockaddr.http); - snprintf(tbuf, 256, "Running on %s %d %d\n", + const Comm::ConnectionPointer conn = icpLocateOutConn(S); + if (!Comm::IsConnOpen(conn)) { + debugs(27, DBG_IMPORTANT, "send_announce: Cannot send to " << host << " primary IP '" << S << "'"); + return; + } + + snprintf(tbuf, 256, "Running on %s %d %u\n", getMyHostname(), getMyPort(), - (int) Config.Port.icp); + conn->local.GetPort()); // NP: advertise the port this peer should be able to contact strcat(sndbuf, tbuf); if (Config.adminEmail) { @@ -110,10 +122,6 @@ } } - Ip::Address S = ia->in_addrs[0]; - S.SetPort(port); - assert(Comm::IsConnOpen(icpOutgoingConn)); - - if (comm_udp_sendto(icpOutgoingConn->fd, S, sndbuf, strlen(sndbuf) + 1) < 0) - debugs(27, 1, "ERROR: Failed to announce to " << S << " from " << icpOutgoingConn->local << ": " << xstrerror()); + if (comm_udp_sendto(conn->fd, S, sndbuf, strlen(sndbuf) + 1) < 0) + debugs(27, DBG_IMPORTANT, "ERROR: Failed to announce to " << S << " from " << conn->local << ": " << xstrerror()); } === modified file 'src/snmp_core.cc' --- src/snmp_core.cc 2012-01-20 18:55:04 +0000 +++ src/snmp_core.cc 2012-03-06 12:59:11 +0000 @@ -31,10 +31,12 @@ */ #include "squid-old.h" #include "acl/FilledChecklist.h" +#include "anyp/PortList.h" #include "base/CbcPointer.h" #include "comm.h" #include "comm/Connection.h" #include "comm/Loops.h" +#include "comm/UdpOpenDialer.h" #include "ipc/StartListening.h" #include "ip/Address.h" #include "ip/tools.h" @@ -42,32 +44,11 @@ #include "snmp/Forwarder.h" -/// dials snmpConnectionOpened call -class SnmpListeningStartedDialer: public CallDialer, - public Ipc::StartListeningCb -{ -public: - typedef void (*Handler)(const Comm::ConnectionPointer &conn, int errNo); - 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)(conn, errNo); } - -public: - Handler handler; -}; - - static void snmpPortOpened(const Comm::ConnectionPointer &conn, int errNo); - mib_tree_entry *mib_tree_head; mib_tree_entry *mib_tree_last; - -Comm::ConnectionPointer snmpIncomingConn; -Comm::ConnectionPointer snmpOutgoingConn; +bool snmpActive = false; 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,...); @@ -88,14 +69,7 @@ static mib_tree_entry *snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current); extern "C" void snmpSnmplibDebug(int lvl, char *buf); -/* - * The functions used during startup: - * snmpInit - * snmpConnectionOpen - * snmpConnectionClose - */ - -/* +/** * Turns the MIB into a Tree structure. Called during the startup process. */ void @@ -287,83 +261,48 @@ } void -snmpConnectionOpen(void) +snmpOpenPorts(void) { - debugs(49, 5, "snmpConnectionOpen: Called"); - - if (Config.Port.snmp <= 0) + if (!Config.Sockaddr.snmp) return; - snmpIncomingConn = new Comm::Connection; - snmpIncomingConn->local = Config.Addrs.snmp_incoming; - snmpIncomingConn->local.SetPort(Config.Port.snmp); - - if (!Ip::EnableIpv6 && !snmpIncomingConn->local.SetIPv4()) { - debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << snmpIncomingConn->local << " is not an IPv4 address."); - fatal("SNMP port cannot be opened."); - } - /* split-stack for now requires IPv4-only SNMP */ - if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && snmpIncomingConn->local.IsAnyAddr()) { - snmpIncomingConn->local.SetIPv4(); - } - - AsyncCall::Pointer call = asyncCall(49, 2, "snmpIncomingConnectionOpened", - SnmpListeningStartedDialer(&snmpPortOpened)); - Ipc::StartListening(SOCK_DGRAM, IPPROTO_UDP, snmpIncomingConn, Ipc::fdnInSnmpSocket, call); - - if (!Config.Addrs.snmp_outgoing.IsNoAddr()) { - snmpOutgoingConn = new Comm::Connection; - snmpOutgoingConn->local = Config.Addrs.snmp_outgoing; - snmpOutgoingConn->local.SetPort(Config.Port.snmp); - - if (!Ip::EnableIpv6 && !snmpOutgoingConn->local.SetIPv4()) { - debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << snmpOutgoingConn->local << " is not an IPv4 address."); - fatal("SNMP port cannot be opened."); - } - /* split-stack for now requires IPv4-only SNMP */ - if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && snmpOutgoingConn->local.IsAnyAddr()) { - snmpOutgoingConn->local.SetIPv4(); - } - AsyncCall::Pointer call = asyncCall(49, 2, "snmpOutgoingConnectionOpened", - SnmpListeningStartedDialer(&snmpPortOpened)); - Ipc::StartListening(SOCK_DGRAM, IPPROTO_UDP, snmpOutgoingConn, Ipc::fdnOutSnmpSocket, call); - } else { - snmpOutgoingConn = snmpIncomingConn; - debugs(1, DBG_IMPORTANT, "Sending SNMP messages from " << snmpOutgoingConn->local); + for (AnyP::PortList *s = Config.Sockaddr.snmp; s; s = s->next) { + s->listenConn = new Comm::Connection; + + AsyncCall::Pointer call = asyncCall(12, 2, + "snmpPortOpened", + Comm::UdpOpenDialer(s->listenConn,&snmpPortOpened)); + + Ipc::StartListening(SOCK_DGRAM, + IPPROTO_UDP, + s->listenConn, + Ipc::fdnInSnmpSocket, call); } } static void snmpPortOpened(const Comm::ConnectionPointer &conn, int errNo) { - if (!Comm::IsConnOpen(conn)) - fatalf("Cannot open SNMP %s Port",(conn->fd == snmpIncomingConn->fd?"receiving":"sending")); - - Comm::SetSelect(conn->fd, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); - - if (conn->fd == snmpIncomingConn->fd) - debugs(1, DBG_IMPORTANT, "Accepting SNMP messages on " << snmpIncomingConn->local); - else if (conn->fd == snmpOutgoingConn->fd) - debugs(1, DBG_IMPORTANT, "Sending SNMP messages from " << snmpOutgoingConn->local); - else - fatalf("Lost SNMP port (%d) on FD %d", (int)conn->local.GetPort(), conn->fd); + if (Comm::IsConnOpen(conn)) { + Comm::SetSelect(conn->fd, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); + debugs(1, DBG_IMPORTANT, "Accepting SNMP messages on " << conn->local); + fd_note(conn->fd, "SNMP port"); + snmpActive = true; + } else + debugs(49, DBG_CRITICAL, "ERROR: Cannot open SNMP port " << conn->local); } void -snmpConnectionClose(void) +snmpClosePorts(void) { - if (Comm::IsConnOpen(snmpIncomingConn)) { - debugs(49, DBG_IMPORTANT, "Closing SNMP receiving port " << snmpIncomingConn->local); - snmpIncomingConn->close(); - } - snmpIncomingConn = NULL; + for (AnyP::PortList *s = Config.Sockaddr.snmp; s; s = s->next) { + if (!Comm::IsConnOpen(s->listenConn)) + continue; - if (Comm::IsConnOpen(snmpOutgoingConn) && snmpIncomingConn != snmpOutgoingConn) { - // Perform OUT port closure so as not to step on IN port when sharing a conn. - debugs(49, DBG_IMPORTANT, "Closing SNMP sending port " << snmpOutgoingConn->local); - snmpOutgoingConn->close(); + s->listenConn->close(); + debugs(12, DBG_IMPORTANT, "Stop accepting SNMP on " << s->listenConn->local); } - snmpOutgoingConn = NULL; + snmpActive = false; } /* === modified file 'src/snmp_core.h' --- src/snmp_core.h 2011-06-04 12:48:45 +0000 +++ src/snmp_core.h 2012-03-06 12:50:45 +0000 @@ -35,6 +35,7 @@ extern struct snmp_pdu* snmpAgentResponse(struct snmp_pdu* PDU); extern AggrType snmpAggrType(oid* Current, snint CurrentLen); -extern Comm::ConnectionPointer snmpOutgoingConn; +/// whether any SNMP ports are currently open +extern bool snmpActive; #endif /* SQUID_SNMP_CORE_H */ === modified file 'src/stat.cc' --- src/stat.cc 2012-01-20 18:55:04 +0000 +++ src/stat.cc 2012-03-06 13:05:46 +0000 @@ -33,6 +33,7 @@ */ #include "squid-old.h" +#include "comm/Loops.h" #include "event.h" #include "format/Token.h" #include "StoreClient.h" @@ -1504,9 +1505,9 @@ * Cache Digest Stuff */ C->cd.on_xition_count.enumInit(CacheDigestHashFuncCount); - C->comm_icp_incoming.enumInit(INCOMING_ICP_MAX); + C->comm_udp_incoming.enumInit(INCOMING_UDP_MAX); C->comm_dns_incoming.enumInit(INCOMING_DNS_MAX); - C->comm_http_incoming.enumInit(INCOMING_HTTP_MAX); + C->comm_tcp_incoming.enumInit(INCOMING_TCP_MAX); C->select_fds_hist.enumInit(256); /* was SQUID_MAXFD, but it is way too much. It is OK to crop this statistics */ } @@ -1524,9 +1525,9 @@ C->icp.replySvcTime.clear(); C->dns.svcTime.clear(); C->cd.on_xition_count.clear(); - C->comm_icp_incoming.clear(); + C->comm_udp_incoming.clear(); C->comm_dns_incoming.clear(); - C->comm_http_incoming.clear(); + C->comm_tcp_incoming.clear(); C->select_fds_hist.clear(); } @@ -1551,8 +1552,9 @@ dest->icp.replySvcTime=orig->icp.replySvcTime; dest->dns.svcTime=orig->dns.svcTime; dest->cd.on_xition_count=orig->cd.on_xition_count; - dest->comm_icp_incoming=orig->comm_icp_incoming; - dest->comm_http_incoming=orig->comm_http_incoming; + dest->comm_udp_incoming=orig->comm_udp_incoming; + dest->comm_dns_incoming=orig->comm_dns_incoming; + dest->comm_tcp_incoming=orig->comm_tcp_incoming; dest->select_fds_hist=orig->select_fds_hist; } === modified file 'src/structs.h' --- src/structs.h 2012-02-03 04:07:36 +0000 +++ src/structs.h 2012-03-04 12:14:18 +0000 @@ -145,7 +145,9 @@ class RemovalPolicySettings; class external_acl; class Store; -struct http_port_list; +namespace AnyP { +struct PortList; +} class SwapDir; /// Used for boolean enabled/disabled options with complex default logic. @@ -232,23 +234,17 @@ acl_size_t *ReplyBodySize; struct { - unsigned short icp; + AnyP::PortList *http; +#if USE_SSL + AnyP::PortList *https; +#endif + AnyP::PortList *icp; #if USE_HTCP - - unsigned short htcp; + AnyP::PortList *htcp; #endif #if SQUID_SNMP - - unsigned short snmp; -#endif - } Port; - - struct { - http_port_list *http; -#if USE_SSL - http_port_list *https; -#endif - + AnyP::PortList *snmp; +#endif } Sockaddr; #if SQUID_SNMP @@ -350,11 +346,7 @@ } Announce; struct { - - Ip::Address udp_incoming; - Ip::Address udp_outgoing; #if SQUID_SNMP - Ip::Address snmp_incoming; Ip::Address snmp_outgoing; #endif /* FIXME INET6 : this should really be a CIDR value */ @@ -556,12 +548,12 @@ #endif struct { - int icp_average; + int udp_average; int dns_average; - int http_average; - int icp_min_poll; + int tcp_average; + int udp_min_poll; int dns_min_poll; - int http_min_poll; + int tcp_min_poll; } comm_incoming; int max_open_disk_fds; int uri_whitespace; @@ -643,6 +635,8 @@ int client_ip_max_connections; struct { + Ip::Address incomingAddr; + Ip::Address outgoingAddr; int v4_first; ///< Place IPv4 first in the order of DNS results. ssize_t packet_max; ///< maximum size EDNS advertised for DNS replies. } dns; === modified file 'src/tools.cc' --- src/tools.cc 2012-01-20 18:55:04 +0000 +++ src/tools.cc 2012-03-09 01:13:34 +0000 @@ -35,11 +35,12 @@ #include "squid-old.h" #include "base/Subscription.h" #include "fde.h" +#include "htcp.h" #include "ICP.h" #include "ip/Intercept.h" #include "ip/QosConfig.h" #include "MemBuf.h" -#include "ProtoPort.h" +#include "anyp/PortList.h" #include "SquidMath.h" #include "SquidTime.h" #include "ipc/Kids.h" @@ -88,19 +89,18 @@ void releaseServerSockets(void) { - int i; - /* Release the main ports as early as possible */ - - // clear both http_port and https_port lists. - for (i = 0; i < NHttpSockets; i++) { - if (HttpSockets[i] >= 0) - close(HttpSockets[i]); - } - - // clear icp_port's - icpConnectionClose(); - - // XXX: Why not the HTCP, SNMP, DNS ports as well? + // Release the main ports as early as possible + clientHttpConnectionsClose(); + icpClosePorts(); +#if USE_HTCP + htcpClosePorts(); +#endif +#if SQUID_SNMP + snmpClosePorts(); +#endif + + // XXX: Why not the DNS ports as well? + // XXX: why does this differ from main closeServerConnections() anyway ? } static char * @@ -1258,7 +1258,7 @@ int getMyPort(void) { - http_port_list *p = NULL; + AnyP::PortList *p = NULL; if ((p = Config.Sockaddr.http)) { // skip any special interception ports while (p && (p->intercepted || p->spoof_client_ip)) === modified file 'src/win32.cc' --- src/win32.cc 2012-01-20 18:55:04 +0000 +++ src/win32.cc 2012-03-09 01:37:49 +0000 @@ -159,9 +159,8 @@ return 0; } - -int Win32__WSAFDIsSet(int fd, fd_set FAR * set - ) +int +Win32__WSAFDIsSet(int fd, fd_set FAR * set) { fde *F = &fd_table[fd]; SOCKET s = F->win32.handle;