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