]> git.ipfire.org Git - thirdparty/squid.git/blame - src/adaptation/ServiceConfig.cc
Renamed squid.h to squid-old.h and config.h to squid.h
[thirdparty/squid.git] / src / adaptation / ServiceConfig.cc
CommitLineData
d81a31f1 1/*
b510f3a1 2 * DEBUG: section 93 Adaptation
d81a31f1
AR
3 */
4
f7f3304a 5#include "squid-old.h"
d81a31f1
AR
6#include "ConfigParser.h"
7#include "adaptation/ServiceConfig.h"
3496b53a 8#include "ip/tools.h"
c25c2836 9#include <set>
d81a31f1 10
26ac0430 11Adaptation::ServiceConfig::ServiceConfig():
e1381638 12 port(-1), method(methodNone), point(pointNone),
2dba5b8e
CT
13 bypass(false), maxConn(-1), onOverload(srvWait),
14 routing(false), ipv6(false)
d81a31f1
AR
15{}
16
17const char *
18Adaptation::ServiceConfig::methodStr() const
19{
20 return Adaptation::methodStr(method);
21}
22
23const char *
24Adaptation::ServiceConfig::vectPointStr() const
25{
26 return Adaptation::vectPointStr(point);
27}
28
29Adaptation::Method
30Adaptation::ServiceConfig::parseMethod(const char *str) const
31{
32 if (!strncasecmp(str, "REQMOD", 6))
33 return Adaptation::methodReqmod;
34
35 if (!strncasecmp(str, "RESPMOD", 7))
36 return Adaptation::methodRespmod;
37
38 return Adaptation::methodNone;
39}
40
41Adaptation::VectPoint
42Adaptation::ServiceConfig::parseVectPoint(const char *service_configConfig) const
43{
44 const char *t = service_configConfig;
45 const char *q = strchr(t, '_');
46
47 if (q)
48 t = q + 1;
49
50 if (!strcasecmp(t, "precache"))
51 return Adaptation::pointPreCache;
52
53 if (!strcasecmp(t, "postcache"))
54 return Adaptation::pointPostCache;
55
56 return Adaptation::pointNone;
57}
58
59bool
60Adaptation::ServiceConfig::parse()
61{
29bf4910 62 String method_point;
d81a31f1
AR
63
64 ConfigParser::ParseString(&key);
65 ConfigParser::ParseString(&method_point);
29bf4910
CT
66 method = parseMethod(method_point.termedBuf());
67 point = parseVectPoint(method_point.termedBuf());
d81a31f1 68
a22e6cd3
AR
69 // reset optional parameters in case we are reconfiguring
70 bypass = routing = false;
71
72 // handle optional service name=value parameters
8e2fb579 73 bool grokkedUri = false;
2dba5b8e 74 bool onOverloadSet = false;
c25c2836 75 std::set<std::string> options;
e29ccb57 76
a22e6cd3 77 while (char *option = strtok(NULL, w_space)) {
c25c2836
CT
78 const char *name = option;
79 const char *value = "";
a22e6cd3 80 if (strcmp(option, "0") == 0) { // backward compatibility
c25c2836
CT
81 name = "bypass";
82 value = "off";
83 debugs(3, opt_parse_cfg_only?0:1, "UPGRADE: Please use 'bypass=off' option to disable service bypass");
84 } else if (strcmp(option, "1") == 0) { // backward compatibility
85 name = "bypass";
86 value = "on";
87 debugs(3, opt_parse_cfg_only?0:1, "UPGRADE: Please use 'bypass=on' option to enable service bypass");
88 } else {
89 char *eq = strstr(option, "=");
90 const char *sffx = strstr(option, "://");
91 if (!eq || (sffx && sffx < eq)) { //no "=" or has the form "icap://host?arg=val"
92 name = "uri";
93 value = option;
94 } else { // a normal name=value option
95 *eq = '\0'; // terminate option name
96 value = eq + 1; // skip '='
97 }
a22e6cd3
AR
98 }
99
c25c2836
CT
100 // Check if option is set twice
101 if (options.find(name) != options.end()) {
e29ccb57 102 debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " <<
c25c2836
CT
103 "Duplicate option \"" << name << "\" in adaptation service definition");
104 return false;
a22e6cd3 105 }
c25c2836 106 options.insert(name);
a22e6cd3 107
a22e6cd3 108 bool grokked = false;
2dba5b8e 109 if (strcmp(name, "bypass") == 0) {
a22e6cd3 110 grokked = grokBool(bypass, name, value);
2dba5b8e 111 } else if (strcmp(name, "routing") == 0)
a22e6cd3 112 grokked = grokBool(routing, name, value);
8e2fb579
AR
113 else if (strcmp(name, "uri") == 0)
114 grokked = grokkedUri = grokUri(value);
3496b53a 115 else if (strcmp(name, "ipv6") == 0) {
e6713f4e 116 grokked = grokBool(ipv6, name, value);
3496b53a
AJ
117 if (grokked && ipv6 && !Ip::EnableIpv6)
118 debugs(3, DBG_IMPORTANT, "WARNING: IPv6 is disabled. ICAP service option ignored.");
2dba5b8e
CT
119 } else if (strcmp(name, "max-conn") == 0)
120 grokked = grokLong(maxConn, name, value);
121 else if (strcmp(name, "on-overload") == 0) {
122 grokked = grokOnOverload(onOverload, value);
123 onOverloadSet = true;
e1e90d26
AR
124 } else
125 grokked = grokExtension(name, value);
126
a22e6cd3
AR
127 if (!grokked)
128 return false;
129 }
130
2dba5b8e
CT
131 // set default on-overload value if needed
132 if (!onOverloadSet)
133 onOverload = bypass ? srvBypass : srvWait;
134
c25c2836
CT
135 // is the service URI set?
136 if (!grokkedUri) {
e29ccb57 137 debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " <<
c25c2836 138 "No \"uri\" option in adaptation service definition");
a22e6cd3
AR
139 return false;
140 }
d81a31f1 141
a22e6cd3 142 debugs(3,5, cfg_filename << ':' << config_lineno << ": " <<
e1381638
AJ
143 "adaptation_service " << key << ' ' <<
144 methodStr() << "_" << vectPointStr() << ' ' <<
145 bypass << routing << ' ' <<
146 uri);
a22e6cd3
AR
147
148 return true;
149}
150
151bool
152Adaptation::ServiceConfig::grokUri(const char *value)
153{
d81a31f1 154 // TODO: find core code that parses URLs and extracts various parts
5957a4c9 155 // AYJ: most of this is duplicate of urlParse() in src/url.cc
d81a31f1 156
a22e6cd3
AR
157 if (!value || !*value) {
158 debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
159 "empty adaptation service URI");
160 return false;
161 }
162
163 uri = value;
164
d81a31f1
AR
165 // extract scheme and use it as the service_configConfig protocol
166 const char *schemeSuffix = "://";
a22e6cd3
AR
167 const String::size_type schemeEnd = uri.find(schemeSuffix);
168 if (schemeEnd != String::npos)
b2f458b7 169 protocol=uri.substr(0,schemeEnd);
826a1fed 170
26ac0430
AJ
171 debugs(3, 5, HERE << cfg_filename << ':' << config_lineno << ": " <<
172 "service protocol is " << protocol);
826a1fed
FC
173
174 if (protocol.size() == 0)
26ac0430 175 return false;
d81a31f1
AR
176
177 // skip scheme
c1945e7d 178 const char *s = uri.termedBuf() + protocol.size() + strlen(schemeSuffix);
d81a31f1
AR
179
180 const char *e;
181
182 bool have_port = false;
183
5957a4c9
AJ
184 int len = 0;
185 if (*s == '[') {
186 const char *t;
187 if ((t = strchr(s, ']')) == NULL)
188 return false;
189
190 s++;
191 len = t - s;
192 if ((e = strchr(t, ':')) != NULL) {
193 have_port = true;
194 } else if ((e = strchr(t, '/')) != NULL) {
195 have_port = false;
196 } else {
197 return false;
198 }
792beadc 199 } else {
5957a4c9
AJ
200 if ((e = strchr(s, ':')) != NULL) {
201 have_port = true;
202 } else if ((e = strchr(s, '/')) != NULL) {
203 have_port = false;
204 } else {
205 return false;
206 }
207 len = e - s;
d81a31f1
AR
208 }
209
d81a31f1
AR
210 host.limitInit(s, len);
211 s = e;
212
26ac0430 213 port = -1;
d81a31f1
AR
214 if (have_port) {
215 s++;
216
217 if ((e = strchr(s, '/')) != NULL) {
218 char *t;
26ac0430 219 const unsigned long p = strtoul(s, &t, 0);
d81a31f1 220
26ac0430
AJ
221 if (p > 65535) // port value is too high
222 return false;
d81a31f1
AR
223
224 port = static_cast<int>(p);
225
226 if (t != e) // extras after the port
227 return false;
228
229 s = e;
230
231 if (s[0] != '/')
232 return false;
233 }
234 }
235
236 // if no port, the caller may use service_configConfigs or supply the default if neeeded
237
238 s++;
239 e = strchr(s, '\0');
240 len = e - s;
241
242 if (len > 1024) {
243 debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
26ac0430 244 "long resource name (>1024), probably wrong");
d81a31f1
AR
245 }
246
247 resource.limitInit(s, len + 1);
a22e6cd3
AR
248 return true;
249}
250
d81a31f1 251
a22e6cd3
AR
252bool
253Adaptation::ServiceConfig::grokBool(bool &var, const char *name, const char *value)
254{
255 if (!strcmp(value, "0") || !strcmp(value, "off"))
256 var = false;
e1381638 257 else if (!strcmp(value, "1") || !strcmp(value, "on"))
a22e6cd3
AR
258 var = true;
259 else {
d81a31f1 260 debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
a22e6cd3
AR
261 "wrong value for boolean " << name << "; " <<
262 "'0', '1', 'on', or 'off' expected but got: " << value);
d81a31f1
AR
263 return false;
264 }
265
266 return true;
267}
e1e90d26 268
2dba5b8e
CT
269bool
270Adaptation::ServiceConfig::grokLong(long &var, const char *name, const char *value)
271{
272 char *bad = NULL;
273 const long p = strtol(value, &bad, 0);
274 if (p < 0 || bad == value) {
275 debugs(3, DBG_CRITICAL, "ERROR: " << cfg_filename << ':' <<
276 config_lineno << ": " << "wrong value for " << name << "; " <<
277 "a non-negative integer expected but got: " << value);
278 return false;
279 }
280 var = p;
281 return true;
282}
283
284bool
285Adaptation::ServiceConfig::grokOnOverload(SrvBehaviour &var, const char *value)
286{
287 if (strcmp(value, "block") == 0)
288 var = srvBlock;
289 else if (strcmp(value, "bypass") == 0)
290 var = srvBypass;
291 else if (strcmp(value, "wait") == 0)
292 var = srvWait;
293 else if (strcmp(value, "force") == 0)
294 var = srvForce;
295 else {
296 debugs(3, DBG_CRITICAL, "ERROR: " << cfg_filename << ':' <<
297 config_lineno << ": " << "wrong value for on-overload; " <<
298 "'block', 'bypass', 'wait' or 'force' expected but got: " << value);
299 return false;
300 }
301 return true;
302}
303
e1e90d26
AR
304bool
305Adaptation::ServiceConfig::grokExtension(const char *name, const char *value)
306{
307 // we do not accept extensions by default
6666da11
AR
308 debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " <<
309 "ERROR: unknown adaptation service option: " <<
310 name << '=' << value);
e1e90d26
AR
311 return false;
312}