lp:3p2-ecap r11136: Polished to address Squid Project review comments. === modified file 'configure.ac' --- configure.ac 2011-02-21 04:32:39 +0000 +++ configure.ac 2011-03-08 20:27:37 +0000 @@ -896,44 +896,44 @@ esac AC_MSG_RESULT([$squid_opt_use_ecap, explicitly]) ], [ squid_opt_use_ecap=no; AC_MSG_RESULT([$squid_opt_use_ecap, implicitly]) ] ) dnl Necessary if the first PKG_CHECK_MODULES call is conditional PKG_PROG_PKG_CONFIG dnl Perform configuration consistency checks for eCAP if test "x$squid_opt_use_ecap" = "xyes"; then dnl eCAP support requires loadable modules, which are enabled by default if test "x$enable_loadable_modules" != "xyes" then AC_MSG_ERROR([eCAP support requires loadable modules. Please do not use --disable-loadable-modules with --enable-ecap.]); fi - dnl eCAP support requires libecap - dnl This Squid supports libecap v0.2.x - dnl Use EXT prefix or libtool will get confused with two libecaps: - dnl one "external" (that we check for here) and one our own convenience lib + dnl eCAP support requires libecap. + dnl This Squid supports libecap v0.2.x. + dnl Use EXT prefix so that make and libtool messages distinguish between + dnl external libecap (that we check for here) and our own convenience lib. PKG_CHECK_MODULES(EXTLIBECAP, [libecap > 0.2 libecap < 0.3]) fi AM_CONDITIONAL(USE_ECAP, test "x$squid_opt_use_ecap" = "xyes") if test "x$squid_opt_use_ecap" = "xyes"; then AC_DEFINE(USE_ECAP,1,[Enable eCAP support]) ECAP_LIBS="ecap/libxecap.la" squid_opt_use_adaptation=yes else AC_DEFINE(USE_ECAP,0,[Disable eCAP support]) ECAP_LIBS="" fi dnl convenience library AC_SUBST(ECAP_LIBS) dnl enable adaptation if requested by specific adaptation mechanisms AM_CONDITIONAL(USE_ADAPTATION, test "x$squid_opt_use_adaptation" = "xyes") if test "x$squid_opt_use_adaptation" = "xyes" === modified file 'src/Server.cc' --- src/Server.cc 2010-12-15 17:52:35 +0000 +++ src/Server.cc 2011-03-08 20:42:13 +0000 @@ -776,41 +776,41 @@ // TODO: bypass if possible if (entry->isEmpty()) { debugs(11,9, HERE << "creating ICAP error entry after ICAP failure"); ErrorState *err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request); err->xerrno = ERR_DETAIL_ICAP_RESPMOD_EARLY; fwd->fail(err); fwd->dontRetry(true); } else if (request) { // update logged info directly request->detailError(ERR_ICAP_FAILURE, ERR_DETAIL_ICAP_RESPMOD_LATE); } abortTransaction("ICAP failure"); } // adaptation service wants us to deny HTTP client access to this response void ServerStateData::handleAdaptationBlocked(const Adaptation::Answer &answer) { - debugs(11,5, HERE << "handleAdaptationBlocked: " << answer.ruleId); + debugs(11,5, HERE << answer.ruleId); if (abortOnBadEntry("entry went bad while ICAP aborted")) return; if (!entry->isEmpty()) { // too late to block (should not really happen) if (request) request->detailError(ERR_ICAP_FAILURE, ERR_DETAIL_RESPMOD_BLOCK_LATE); abortTransaction("late adaptation block"); return; } debugs(11,7, HERE << "creating adaptation block response"); err_type page_id = aclGetDenyInfoPage(&Config.denyInfoList, answer.ruleId.termedBuf(), 1); if (page_id == ERR_NONE) page_id = ERR_ACCESS_DENIED; ErrorState *err = errorCon(page_id, HTTP_FORBIDDEN, request); err->xerrno = ERR_DETAIL_RESPMOD_BLOCK_EARLY; === modified file 'src/adaptation/Config.h' --- src/adaptation/Config.h 2011-02-17 19:27:54 +0000 +++ src/adaptation/Config.h 2011-03-08 21:30:40 +0000 @@ -47,30 +47,30 @@ ServiceConfigs serviceConfigs; Config(); virtual ~Config(); void parseService(void); void freeService(void); void dumpService(StoreEntry *, const char *) const; ServicePointer findService(const String&); virtual void finalize(); protected: /// creates service configuration object that will parse and keep cfg info virtual ServiceConfig *newServiceConfig() const; private: Config(const Config &); // unsupported Config &operator =(const Config &); // unsupported - virtual ServicePointer createService(ServiceConfigPointer cfg) = 0; + virtual ServicePointer createService(const ServiceConfigPointer &cfg) = 0; static void ParseServiceGroup(ServiceGroupPointer group); static void FreeServiceGroups(void); static void DumpServiceGroups(StoreEntry *, const char *); }; } // namespace Adaptation #endif /* SQUID_ADAPTATION__CONFIG_H */ === modified file 'src/adaptation/Makefile.am' --- src/adaptation/Makefile.am 2011-02-17 19:11:06 +0000 +++ src/adaptation/Makefile.am 2011-03-08 21:38:49 +0000 @@ -28,24 +28,23 @@ Initiate.cc \ Initiate.h \ Initiator.cc \ Initiator.h \ Iterator.cc \ Iterator.h \ Message.cc \ Message.h \ Service.cc \ Service.h \ ServiceConfig.cc \ ServiceConfig.h \ ServiceGroups.cc \ ServiceGroups.h \ ServiceFilter.cc \ ServiceFilter.h \ History.cc \ History.h # add libraries for specific adaptation schemes -libadaptation_la_LDFLAGS = $(EXTLIBECAP_LIBS) -libadaptation_la_LIBADD = $(ECAP_LIBS) $(ICAP_LIBS) +libadaptation_la_LIBADD = $(EXTLIBECAP_LIBS) $(ECAP_LIBS) $(ICAP_LIBS) libadaptation_la_DEPENDENCIES = $(ECAP_LIBS) $(ICAP_LIBS) === modified file 'src/adaptation/Service.cc' --- src/adaptation/Service.cc 2010-12-18 00:31:53 +0000 +++ src/adaptation/Service.cc 2011-03-08 22:56:17 +0000 @@ -1,30 +1,30 @@ /* * DEBUG: section 93 Adaptation */ #include "squid.h" #include "HttpRequest.h" #include "adaptation/ServiceFilter.h" #include "adaptation/Service.h" -Adaptation::Service::Service(ServiceConfigPointer aConfig): theConfig(aConfig) +Adaptation::Service::Service(const ServiceConfigPointer &aConfig): theConfig(aConfig) { Must(theConfig != NULL); debugs(93,3, HERE << "creating adaptation service " << cfg().key); } Adaptation::Service::~Service() {} void Adaptation::Service::finalize() { } bool Adaptation::Service::broken() const { return probed() && !up(); } bool Adaptation::Service::wants(const ServiceFilter &filter) const === modified file 'src/adaptation/Service.h' --- src/adaptation/Service.h 2010-12-18 00:31:53 +0000 +++ src/adaptation/Service.h 2011-03-08 22:53:38 +0000 @@ -7,41 +7,41 @@ #include "adaptation/Elements.h" #include "adaptation/ServiceConfig.h" // TODO: Move src/ICAP/ICAPServiceRep.h API comments here and update them class HttpMsg; class HttpRequest; namespace Adaptation { // manages adaptation service configuration in squid.conf // specific adaptation mechanisms extend this class class Service: public RefCountable { public: typedef RefCount Pointer; typedef String Id; public: - explicit Service(ServiceConfigPointer aConfig); + explicit Service(const ServiceConfigPointer &aConfig); virtual ~Service(); virtual bool probed() const = 0; // see comments above virtual bool broken() const; virtual bool up() const = 0; // see comments above virtual Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause) = 0; bool wants(const ServiceFilter &filter) const; // the methods below can only be called on an up() service virtual bool wantsUrl(const String &urlPath) const = 0; // called by transactions to report service failure virtual void noteFailure() = 0; const ServiceConfig &cfg() const { return *theConfig; } virtual void finalize(); // called after creation === modified file 'src/adaptation/ServiceConfig.cc' --- src/adaptation/ServiceConfig.cc 2011-02-18 23:58:13 +0000 +++ src/adaptation/ServiceConfig.cc 2011-03-08 22:58:54 +0000 @@ -233,24 +233,25 @@ Adaptation::ServiceConfig::grokBool(bool &var, const char *name, const char *value) { if (!strcmp(value, "0") || !strcmp(value, "off")) var = false; else if (!strcmp(value, "1") || !strcmp(value, "on")) var = true; else { debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " << "wrong value for boolean " << name << "; " << "'0', '1', 'on', or 'off' expected but got: " << value); return false; } return true; } bool Adaptation::ServiceConfig::grokExtension(const char *name, const char *value) { // we do not accept extensions by default - debugs(3, 0, cfg_filename << ':' << config_lineno << ": " << - "unknown adaptation service option: " << name << '=' << value); + debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " << + "ERROR: unknown adaptation service option: " << + name << '=' << value); return false; } === modified file 'src/adaptation/ecap/Config.cc' --- src/adaptation/ecap/Config.cc 2010-12-18 00:31:53 +0000 +++ src/adaptation/ecap/Config.cc 2011-03-08 21:31:51 +0000 @@ -16,35 +16,35 @@ Adaptation::Ecap::Config::~Config() { } void Adaptation::Ecap::Config::finalize() { Adaptation::Config::finalize(); Host::Register(); CheckUnusedAdapterServices(AllServices()); } Adaptation::ServiceConfig * Adaptation::Ecap::Config::newServiceConfig() const { return new ServiceConfig(); } Adaptation::ServicePointer -Adaptation::Ecap::Config::createService(ServiceConfigPointer cfg) +Adaptation::Ecap::Config::createService(const ServiceConfigPointer &cfg) { return new Adaptation::Ecap::ServiceRep(cfg); } /* ServiceConfig */ bool Adaptation::Ecap::ServiceConfig::grokExtension(const char *name, const char *value) { extensions.push_back(std::make_pair(name, value)); return true; } === modified file 'src/adaptation/ecap/Config.h' --- src/adaptation/ecap/Config.h 2011-02-21 04:39:04 +0000 +++ src/adaptation/ecap/Config.h 2011-03-08 21:31:51 +0000 @@ -29,29 +29,29 @@ }; /// General eCAP configuration class Config: public Adaptation::Config { public: Config(); ~Config(); virtual void finalize(); protected: virtual Adaptation::ServiceConfig *newServiceConfig() const; private: Config(const Config &); // not implemented Config &operator =(const Config &); // not implemented - virtual Adaptation::ServicePointer createService(ServiceConfigPointer cfg); + virtual Adaptation::ServicePointer createService(const ServiceConfigPointer &cfg); }; extern Config TheConfig; } // namespace Ecap } // namespace Adaptation #endif /* SQUID_ECAP_CONFIG_H */ === modified file 'src/adaptation/ecap/Makefile.am' --- src/adaptation/ecap/Makefile.am 2011-02-17 19:11:06 +0000 +++ src/adaptation/ecap/Makefile.am 2011-03-08 21:37:40 +0000 @@ -1,26 +1,26 @@ include $(top_srcdir)/src/Common.am include $(top_srcdir)/src/TestHeaders.am noinst_LTLIBRARIES = libxecap.la libxecap_la_SOURCES = \ Config.h \ Config.cc \ Host.h \ Host.cc \ MessageRep.h \ MessageRep.cc \ ServiceRep.h \ ServiceRep.cc \ XactionRep.h \ XactionRep.cc \ \ Registry.h # add libecap using its pkg-config-produced configuration variables -libxecap_la_CPPFLAGS = $(EXTLIBECAP_CFLAGS) +libxecap_la_CXXFLAGS = $(EXTLIBECAP_CFLAGS) -## It is tempting to put libxecap_la_LDFLAGS here, but it leads to weird +## It is tempting to put libxecap_la_LDFLAGS/LIBADD here, but it leads to weird ## linking errors. For example, "make clean all" works, but rebuilding after ## modifying a single source file leads to libtool's "file not found" errors. -## libxecap_la_LDFLAGS = $(EXTLIBECAP_LIBS) +## libxecap_la_LIBADD = $(EXTLIBECAP_LIBS) === modified file 'src/adaptation/ecap/ServiceRep.cc' --- src/adaptation/ecap/ServiceRep.cc 2011-02-17 19:27:54 +0000 +++ src/adaptation/ecap/ServiceRep.cc 2011-03-08 22:55:35 +0000 @@ -61,41 +61,41 @@ return Area(i->second.data(), i->second.size()); } return Area(); } void Adaptation::Ecap::ConfigRep::visitEachOption(libecap::NamedValueVisitor &visitor) const { // we may supply the params we know about too, but only if we set host ID visitor.visit(metaBypassable, Area(master.bypass ? "1" : "0", 1)); // visit adapter-specific options (i.e., those not recognized by Squid) typedef Master::Extensions::const_iterator MECI; for (MECI i = master.extensions.begin(); i != master.extensions.end(); ++i) visitor.visit(Name(i->first), Area::FromTempString(i->second)); } -Adaptation::Ecap::ServiceRep::ServiceRep(ServiceConfigPointer cfg): +Adaptation::Ecap::ServiceRep::ServiceRep(const ServiceConfigPointer &cfg): /*AsyncJob("Adaptation::Ecap::ServiceRep"),*/ Adaptation::Service(cfg), isDetached(false) { } Adaptation::Ecap::ServiceRep::~ServiceRep() { } void Adaptation::Ecap::ServiceRep::noteFailure() { assert(false); // XXX: should this be ICAP-specific? } void Adaptation::Ecap::ServiceRep::finalize() { Adaptation::Service::finalize(); theService = FindAdapterService(cfg().uri); if (theService) { === modified file 'src/adaptation/ecap/ServiceRep.h' --- src/adaptation/ecap/ServiceRep.h 2010-12-18 00:31:53 +0000 +++ src/adaptation/ecap/ServiceRep.h 2011-03-08 22:55:17 +0000 @@ -6,41 +6,41 @@ #ifndef SQUID_ECAP_SERVICE_REP_H #define SQUID_ECAP_SERVICE_REP_H #include "adaptation/Service.h" #include "adaptation/forward.h" #include #include namespace Adaptation { namespace Ecap { /* The eCAP service representative maintains information about a single eCAP service that Squid communicates with. One eCAP module may register many eCAP services. */ class ServiceRep : public Adaptation::Service { public: - ServiceRep(ServiceConfigPointer aConfig); + explicit ServiceRep(const ServiceConfigPointer &aConfig); virtual ~ServiceRep(); typedef libecap::shared_ptr AdapterService; virtual void finalize(); virtual bool probed() const; virtual bool up() const; Adaptation::Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause); // the methods below can only be called on an up() service virtual bool wantsUrl(const String &urlPath) const; // called by transactions to report service failure virtual void noteFailure(); virtual const char *status() const; virtual void detach(); === modified file 'src/adaptation/icap/Config.cc' --- src/adaptation/icap/Config.cc 2010-12-18 00:31:53 +0000 +++ src/adaptation/icap/Config.cc 2011-03-08 21:31:51 +0000 @@ -41,41 +41,41 @@ #include "adaptation/icap/ServiceRep.h" #include "HttpRequest.h" #include "HttpReply.h" #include "wordlist.h" Adaptation::Icap::Config Adaptation::Icap::TheConfig; Adaptation::Icap::Config::Config(): preview_enable(0), preview_size(0), allow206_enable(0), connect_timeout_raw(0), io_timeout_raw(0), reuse_connections(0), client_username_header(NULL), client_username_encode(0), repeat(NULL) { } Adaptation::Icap::Config::~Config() { // TODO: delete client_username_header? } Adaptation::ServicePointer -Adaptation::Icap::Config::createService(ServiceConfigPointer cfg) +Adaptation::Icap::Config::createService(const ServiceConfigPointer &cfg) { return new Adaptation::Icap::ServiceRep(cfg); } time_t Adaptation::Icap::Config::connect_timeout(bool bypassable) const { if (connect_timeout_raw > 0) return connect_timeout_raw; // explicitly configured return bypassable ? ::Config.Timeout.peer_connect : ::Config.Timeout.connect; } time_t Adaptation::Icap::Config::io_timeout(bool) const { if (io_timeout_raw > 0) return io_timeout_raw; // explicitly configured // TODO: provide a different default for an ICAP transaction that // can still be bypassed return ::Config.Timeout.read; } === modified file 'src/adaptation/icap/Config.h' --- src/adaptation/icap/Config.h 2010-12-18 00:31:53 +0000 +++ src/adaptation/icap/Config.h 2011-03-08 21:31:51 +0000 @@ -59,30 +59,30 @@ int preview_size; int allow206_enable; time_t connect_timeout_raw; time_t io_timeout_raw; int reuse_connections; char* client_username_header; int client_username_encode; acl_access *repeat; ///< icap_retry ACL in squid.conf int repeat_limit; ///< icap_retry_limit in squid.conf Config(); ~Config(); time_t connect_timeout(bool bypassable) const; time_t io_timeout(bool bypassable) const; private: Config(const Config &); // not implemented Config &operator =(const Config &); // not implemented - virtual Adaptation::ServicePointer createService(ServiceConfigPointer cfg); + virtual Adaptation::ServicePointer createService(const ServiceConfigPointer &cfg); }; extern Config TheConfig; } // namespace Icap } // namespace Adaptation #endif /* SQUID_ICAPCONFIG_H */ === modified file 'src/adaptation/icap/ServiceRep.cc' --- src/adaptation/icap/ServiceRep.cc 2010-12-18 00:31:53 +0000 +++ src/adaptation/icap/ServiceRep.cc 2011-03-08 22:54:35 +0000 @@ -1,38 +1,38 @@ /* * DEBUG: section 93 ICAP (RFC 3507) Client */ #include "squid.h" #include "adaptation/icap/Config.h" #include "adaptation/icap/ModXact.h" #include "adaptation/icap/Options.h" #include "adaptation/icap/OptXact.h" #include "adaptation/icap/ServiceRep.h" #include "base/TextException.h" #include "ConfigParser.h" #include "HttpReply.h" #include "SquidTime.h" CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, ServiceRep); -Adaptation::Icap::ServiceRep::ServiceRep(ServiceConfigPointer svcCfg): +Adaptation::Icap::ServiceRep::ServiceRep(const ServiceConfigPointer &svcCfg): AsyncJob("Adaptation::Icap::ServiceRep"), Adaptation::Service(svcCfg), theOptions(NULL), theOptionsFetcher(0), theLastUpdate(0), isSuspended(0), notifying(false), updateScheduled(false), wasAnnouncedUp(true), // do not announce an "up" service at startup isDetached(false) {} Adaptation::Icap::ServiceRep::~ServiceRep() { Must(!theOptionsFetcher); delete theOptions; } void Adaptation::Icap::ServiceRep::finalize() { Adaptation::Service::finalize(); // use /etc/services or default port if needed === modified file 'src/adaptation/icap/ServiceRep.h' --- src/adaptation/icap/ServiceRep.h 2010-12-18 00:31:53 +0000 +++ src/adaptation/icap/ServiceRep.h 2011-03-08 22:54:53 +0000 @@ -70,41 +70,41 @@ * even if the service is now broken. * * We do not initiate ICAP transactions with a broken service, but will * eventually retry to fetch its options in hope to bring the service up. * * A service that should no longer be used after Squid reconfiguration is * treated as if it does not have a fresh cached OPTIONS response. We do * not try to fetch fresh options for such a service. It should be * auto-destroyed by refcounting when no longer used. */ class ServiceRep : public RefCountable, public Adaptation::Service, public Adaptation::Initiator { public: typedef RefCount Pointer; public: - ServiceRep(ServiceConfigPointer aConfig); + explicit ServiceRep(const ServiceConfigPointer &aConfig); virtual ~ServiceRep(); virtual void finalize(); virtual bool probed() const; // see comments above virtual bool up() const; // see comments above virtual Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause); void callWhenReady(AsyncCall::Pointer &cb); // the methods below can only be called on an up() service bool wantsUrl(const String &urlPath) const; bool wantsPreview(const String &urlPath, size_t &wantedSize) const; bool allows204() const; bool allows206() const; void noteFailure(); // called by transactions to report service failure //AsyncJob virtual methods === modified file 'src/cf.data.pre' --- src/cf.data.pre 2011-02-18 23:58:13 +0000 +++ src/cf.data.pre 2011-03-08 23:12:30 +0000 @@ -6741,44 +6741,46 @@ See also: icap_service routing=1 DOC_END NAME: adaptation_masterx_shared_names TYPE: string IFDEF: USE_ADAPTATION LOC: Adaptation::Config::masterx_shared_name DEFAULT: none DOC_START For each master transaction (i.e., the HTTP request and response sequence, including all related ICAP and eCAP exchanges), Squid maintains a table of metadata. The table entries are (name, value) pairs shared among eCAP and ICAP exchanges. The table is destroyed with the master transaction. This option specifies the table entry names that Squid must accept from and forward to the adaptation transactions. An ICAP REQMOD or RESPMOD transaction may set an entry in the shared table by returning an ICAP header field with a name - specified in adaptation_masterx_shared_names. An eCAP REQMOD or - RESPMOD transaction may set an entry in the shared table by - implementing the libecap::visitEachOption() API to provide an - option with a name specified in adaptation_masterx_shared_names. + specified in adaptation_masterx_shared_names. + + An eCAP REQMOD or RESPMOD transaction may set an entry in the + shared table by implementing the libecap::visitEachOption() API + to provide an option with a name specified in + adaptation_masterx_shared_names. Squid will store and forward the set entry to subsequent adaptation transactions within the same master transaction scope. Only one shared entry name is supported at this time. Example: # share authentication information among ICAP services adaptation_masterx_shared_names X-Subscriber-ID DOC_END NAME: icap_retry TYPE: acl_access IFDEF: ICAP_CLIENT LOC: Adaptation::Icap::TheConfig.repeat DEFAULT_IF_NONE: deny all DOC_START This ACL determines which retriable ICAP transactions are retried. Transactions that received a complete ICAP response and did not have to consume or produce HTTP bodies to receive === modified file 'src/cf_gen_defines' --- src/cf_gen_defines 2010-12-12 05:30:58 +0000 +++ src/cf_gen_defines 2011-03-08 23:18:27 +0000 @@ -1,31 +1,31 @@ #!/usr/bin/awk -f BEGIN { print "/* Generated automatically from cf.data.pre" print " * DO NOT EDIT" print "*/" print "#include \"config.h\"" print "static struct { const char *name; const char *enable; int defined;} defines[] = {" define["USE_DELAY_POOLS"]="--enable-delay-pools" define["FOLLOW_X_FORWARDED_FOR"]="--enable-follow-x-forwarded-for" define["FOLLOW_X_FORWARDED_FOR&&USE_DELAY_POOLS"]="--enable-follow-x-forwarded-for and --enable-delay-pools" - define["FOLLOW_X_FORWARDED_FOR&&ICAP_CLIENT"]="--enable-follow-x-forwarded-for and --enable-icap-client" + define["FOLLOW_X_FORWARDED_FOR&&USE_ADAPTATION"]="--enable-follow-x-forwarded-for and (--enable-icap-client and/or --enable-ecap)" define["FOLLOW_X_FORWARDED_FOR&&LINUX_NETFILTER"]="--enable-follow-x-forwarded-for and --enable-linux-netfilter" define["USE_HTTP_VIOLATIONS"]="--enable-http-violations" define["ICAP_CLIENT"]="--enable-icap-client" define["SQUID_SNMP"]="--enable-snmp" define["USE_ADAPTATION"]="--enable-ecap or --enable-icap-client" define["USE_CACHE_DIGESTS"]="--enable-cache-digests" define["USE_DNSSERVERS"]="--disable-internal-dns" define["!USE_DNSSERVERS"]="--enable-internal-dns" define["USE_ECAP"]="--enable-ecap" define["USE_ERR_LOCALES"]="--enable-auto-locale" define["USE_HTCP"]="--enable-htcp" define["USE_ICMP"]="--enable-icmp" define["USE_IDENT"]="--enable-ident-lookups" define["USE_LOADABLE_MODULES"]="--enable-loadable-modules" define["USE_SQUID_ESI"]="--enable-esi" define["USE_SSL"]="--enable-ssl" define["USE_UNLINKD"]="--enable-unlinkd" define["USE_WCCP"]="--enable-wccp" define["USE_WCCPv2"]="--enable-wccpv2" define["USE_QOS_TOS"]="--enable-zph-qos"