]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/ecap/Host.cc
Bug 1961: pt1: URL handling redesign
[thirdparty/squid.git] / src / adaptation / ecap / Host.cc
1 /*
2 * DEBUG: section 93 eCAP Interface
3 */
4 #include "squid.h"
5 #include <libecap/adapter/service.h>
6 #include <libecap/common/names.h>
7 #include <libecap/common/registry.h>
8 #include "adaptation/ecap/Host.h"
9 #include "adaptation/ecap/MessageRep.h"
10 #include "adaptation/ecap/ServiceRep.h"
11 #include "base/TextException.h"
12 #include "HttpReply.h"
13 #include "HttpRequest.h"
14
15 const libecap::Name Adaptation::Ecap::protocolInternal("internal", libecap::Name::NextId());
16 const libecap::Name Adaptation::Ecap::protocolCacheObj("cache_object", libecap::Name::NextId());
17 const libecap::Name Adaptation::Ecap::protocolIcp("ICP", libecap::Name::NextId());
18 #if USE_HTCP
19 const libecap::Name Adaptation::Ecap::protocolHtcp("Htcp", libecap::Name::NextId());
20 #endif
21 const libecap::Name Adaptation::Ecap::protocolIcy("ICY", libecap::Name::NextId());
22 const libecap::Name Adaptation::Ecap::protocolUnknown("_unknown_", libecap::Name::NextId());
23
24 const libecap::Name Adaptation::Ecap::metaBypassable("bypassable", libecap::Name::NextId());
25
26 /// the host application (i.e., Squid) wrapper registered with libecap
27 static libecap::shared_ptr<Adaptation::Ecap::Host> TheHost;
28
29 Adaptation::Ecap::Host::Host()
30 {
31 // assign our host-specific IDs to well-known names
32 // this code can run only once
33
34 libecap::headerTransferEncoding.assignHostId(HDR_TRANSFER_ENCODING);
35 libecap::headerReferer.assignHostId(HDR_REFERER);
36 libecap::headerContentLength.assignHostId(HDR_CONTENT_LENGTH);
37 libecap::headerVia.assignHostId(HDR_VIA);
38 // TODO: libecap::headerXClientIp.assignHostId(HDR_X_CLIENT_IP);
39 // TODO: libecap::headerXServerIp.assignHostId(HDR_X_SERVER_IP);
40
41 libecap::protocolHttp.assignHostId(AnyP::PROTO_HTTP);
42 libecap::protocolHttps.assignHostId(AnyP::PROTO_HTTPS);
43 libecap::protocolFtp.assignHostId(AnyP::PROTO_FTP);
44 libecap::protocolGopher.assignHostId(AnyP::PROTO_GOPHER);
45 libecap::protocolWais.assignHostId(AnyP::PROTO_WAIS);
46 libecap::protocolUrn.assignHostId(AnyP::PROTO_URN);
47 libecap::protocolWhois.assignHostId(AnyP::PROTO_WHOIS);
48 protocolCacheObj.assignHostId(AnyP::PROTO_CACHE_OBJECT);
49 protocolIcp.assignHostId(AnyP::PROTO_ICP);
50 #if USE_HTCP
51 protocolHtcp.assignHostId(AnyP::PROTO_HTCP);
52 #endif
53 protocolIcy.assignHostId(AnyP::PROTO_ICY);
54 protocolUnknown.assignHostId(AnyP::PROTO_UNKNOWN);
55
56 // allows adapter to safely ignore this in adapter::Service::configure()
57 metaBypassable.assignHostId(1);
58 }
59
60 std::string
61 Adaptation::Ecap::Host::uri() const
62 {
63 return "ecap://squid-cache.org/ecap/hosts/squid";
64 }
65
66 void
67 Adaptation::Ecap::Host::describe(std::ostream &os) const
68 {
69 os << PACKAGE_NAME << " v" << PACKAGE_VERSION;
70 }
71
72 /// Strips libecap version components not affecting compatibility decisions.
73 static SBuf
74 EssentialVersion(const SBuf &raw)
75 {
76 // all libecap x.y.* releases are supposed to be compatible so we strip
77 // everything after the second period
78 const SBuf::size_type minorPos = raw.find('.');
79 const SBuf::size_type microPos = minorPos == SBuf::npos ?
80 SBuf::npos : raw.find('.', minorPos+1);
81 return raw.substr(0, microPos); // becomes raw if microPos is npos
82 }
83
84 /// If "their" libecap version is not compatible with what Squid has been built
85 /// with, then complain and return false.
86 static bool
87 SupportedVersion(const char *vTheir, const char *them)
88 {
89 if (!vTheir || !*vTheir) {
90 debugs(93, DBG_CRITICAL, "ERROR: Cannot use " << them <<
91 " with libecap prior to v1.0.");
92 return false;
93 }
94
95 // we support what we are built with
96 const SBuf vSupported(LIBECAP_VERSION);
97 debugs(93, 2, them << " with libecap v" << vTheir << "; us: v" << vSupported);
98
99 if (EssentialVersion(SBuf(vTheir)) == EssentialVersion(vSupported))
100 return true; // their version is supported
101
102 debugs(93, DBG_CRITICAL, "ERROR: Cannot use " << them <<
103 " with libecap v" << vTheir <<
104 ": incompatible with supported libecap v" << vSupported);
105 return false;
106 }
107
108 void
109 Adaptation::Ecap::Host::noteVersionedService(const char *vGiven, const libecap::weak_ptr<libecap::adapter::Service> &weak)
110 {
111 /*
112 * Check that libecap used to build the service is compatible with ours.
113 * This has to be done using vGiven string and not Service object itself
114 * because dereferencing a Service pointer coming from an unsupported
115 * version is unsafe.
116 */
117 if (SupportedVersion(vGiven, "eCAP service built")) {
118 Must(!weak.expired());
119 RegisterAdapterService(weak.lock());
120 }
121 }
122
123 static int
124 SquidLogLevel(libecap::LogVerbosity lv)
125 {
126 if (lv.critical())
127 return DBG_CRITICAL; // is it a good idea to ignore other flags?
128
129 if (lv.large())
130 return DBG_DATA; // is it a good idea to ignore other flags?
131
132 if (lv.application())
133 return DBG_IMPORTANT; // is it a good idea to ignore other flags?
134
135 return 2 + 2*lv.debugging() + 3*lv.operation() + 2*lv.xaction();
136 }
137
138 std::ostream *
139 Adaptation::Ecap::Host::openDebug(libecap::LogVerbosity lv)
140 {
141 const int squidLevel = SquidLogLevel(lv);
142 const int squidSection = 93; // XXX: this should be a global constant
143 // XXX: Debug.h should provide this to us
144 if ((Debug::level = squidLevel) <= Debug::Levels[squidSection])
145 return &Debug::getDebugOut();
146 else
147 return NULL;
148 }
149
150 void
151 Adaptation::Ecap::Host::closeDebug(std::ostream *debug)
152 {
153 if (debug)
154 Debug::finishDebug();
155 }
156
157 Adaptation::Ecap::Host::MessagePtr
158 Adaptation::Ecap::Host::newRequest() const
159 {
160 return MessagePtr(new Adaptation::Ecap::MessageRep(new HttpRequest));
161 }
162
163 Adaptation::Ecap::Host::MessagePtr
164 Adaptation::Ecap::Host::newResponse() const
165 {
166 return MessagePtr(new Adaptation::Ecap::MessageRep(new HttpReply));
167 }
168
169 void
170 Adaptation::Ecap::Host::Register()
171 {
172 if (!TheHost && SupportedVersion(libecap::VersionString(),
173 "Squid executable dynamically linked")) {
174 TheHost.reset(new Adaptation::Ecap::Host);
175 libecap::RegisterHost(TheHost);
176 }
177 }