]> git.ipfire.org Git - thirdparty/squid.git/blame - src/adaptation/ServiceConfig.cc
Important messages from eCAP adapters were logged with too high level
[thirdparty/squid.git] / src / adaptation / ServiceConfig.cc
CommitLineData
d81a31f1 1/*
b510f3a1 2 * DEBUG: section 93 Adaptation
d81a31f1
AR
3 */
4
5#include "squid.h"
6#include "ConfigParser.h"
7#include "adaptation/ServiceConfig.h"
3496b53a 8#include "ip/tools.h"
d81a31f1 9
26ac0430 10Adaptation::ServiceConfig::ServiceConfig():
e1381638 11 port(-1), method(methodNone), point(pointNone),
e6713f4e 12 bypass(false), routing(false), ipv6(false)
d81a31f1
AR
13{}
14
15const char *
16Adaptation::ServiceConfig::methodStr() const
17{
18 return Adaptation::methodStr(method);
19}
20
21const char *
22Adaptation::ServiceConfig::vectPointStr() const
23{
24 return Adaptation::vectPointStr(point);
25}
26
27Adaptation::Method
28Adaptation::ServiceConfig::parseMethod(const char *str) const
29{
30 if (!strncasecmp(str, "REQMOD", 6))
31 return Adaptation::methodReqmod;
32
33 if (!strncasecmp(str, "RESPMOD", 7))
34 return Adaptation::methodRespmod;
35
36 return Adaptation::methodNone;
37}
38
39Adaptation::VectPoint
40Adaptation::ServiceConfig::parseVectPoint(const char *service_configConfig) const
41{
42 const char *t = service_configConfig;
43 const char *q = strchr(t, '_');
44
45 if (q)
46 t = q + 1;
47
48 if (!strcasecmp(t, "precache"))
49 return Adaptation::pointPreCache;
50
51 if (!strcasecmp(t, "postcache"))
52 return Adaptation::pointPostCache;
53
54 return Adaptation::pointNone;
55}
56
57bool
58Adaptation::ServiceConfig::parse()
59{
60 char *method_point = NULL;
61
62 ConfigParser::ParseString(&key);
63 ConfigParser::ParseString(&method_point);
d81a31f1
AR
64 method = parseMethod(method_point);
65 point = parseVectPoint(method_point);
66
a22e6cd3
AR
67 // reset optional parameters in case we are reconfiguring
68 bypass = routing = false;
69
70 // handle optional service name=value parameters
71 const char *lastOption = NULL;
72 while (char *option = strtok(NULL, w_space)) {
73 if (strcmp(option, "0") == 0) { // backward compatibility
74 bypass = false;
75 continue;
76 }
77 if (strcmp(option, "1") == 0) { // backward compatibility
78 bypass = true;
79 continue;
80 }
81
82 const char *name = option;
83 char *value = strstr(option, "=");
84 if (!value) {
85 lastOption = option;
86 break;
87 }
88 *value = '\0'; // terminate option name
89 ++value; // skip '='
90
91 // TODO: warn if option is set twice?
92 bool grokked = false;
93 if (strcmp(name, "bypass") == 0)
94 grokked = grokBool(bypass, name, value);
e1381638 95 else if (strcmp(name, "routing") == 0)
a22e6cd3 96 grokked = grokBool(routing, name, value);
3496b53a 97 else if (strcmp(name, "ipv6") == 0) {
e6713f4e 98 grokked = grokBool(ipv6, name, value);
3496b53a
AJ
99 if (grokked && ipv6 && !Ip::EnableIpv6)
100 debugs(3, DBG_IMPORTANT, "WARNING: IPv6 is disabled. ICAP service option ignored.");
e6713f4e 101 } else {
a22e6cd3 102 debugs(3, 0, cfg_filename << ':' << config_lineno << ": " <<
e1381638 103 "unknown adaptation service option: " << name << '=' << value);
a22e6cd3
AR
104 }
105 if (!grokked)
106 return false;
107 }
108
109 // what is left must be the service URI
110 if (!grokUri(lastOption))
111 return false;
112
113 // there should be nothing else left
114 if (const char *tail = strtok(NULL, w_space)) {
115 debugs(3, 0, cfg_filename << ':' << config_lineno << ": " <<
e1381638 116 "garbage after adaptation service URI: " << tail);
a22e6cd3
AR
117 return false;
118 }
d81a31f1 119
a22e6cd3 120 debugs(3,5, cfg_filename << ':' << config_lineno << ": " <<
e1381638
AJ
121 "adaptation_service " << key << ' ' <<
122 methodStr() << "_" << vectPointStr() << ' ' <<
123 bypass << routing << ' ' <<
124 uri);
a22e6cd3
AR
125
126 return true;
127}
128
129bool
130Adaptation::ServiceConfig::grokUri(const char *value)
131{
d81a31f1 132 // TODO: find core code that parses URLs and extracts various parts
5957a4c9 133 // AYJ: most of this is duplicate of urlParse() in src/url.cc
d81a31f1 134
a22e6cd3
AR
135 if (!value || !*value) {
136 debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
137 "empty adaptation service URI");
138 return false;
139 }
140
141 uri = value;
142
d81a31f1
AR
143 // extract scheme and use it as the service_configConfig protocol
144 const char *schemeSuffix = "://";
a22e6cd3
AR
145 const String::size_type schemeEnd = uri.find(schemeSuffix);
146 if (schemeEnd != String::npos)
b2f458b7 147 protocol=uri.substr(0,schemeEnd);
826a1fed 148
26ac0430
AJ
149 debugs(3, 5, HERE << cfg_filename << ':' << config_lineno << ": " <<
150 "service protocol is " << protocol);
826a1fed
FC
151
152 if (protocol.size() == 0)
26ac0430 153 return false;
d81a31f1
AR
154
155 // skip scheme
c1945e7d 156 const char *s = uri.termedBuf() + protocol.size() + strlen(schemeSuffix);
d81a31f1
AR
157
158 const char *e;
159
160 bool have_port = false;
161
5957a4c9
AJ
162 int len = 0;
163 if (*s == '[') {
164 const char *t;
165 if ((t = strchr(s, ']')) == NULL)
166 return false;
167
168 s++;
169 len = t - s;
170 if ((e = strchr(t, ':')) != NULL) {
171 have_port = true;
172 } else if ((e = strchr(t, '/')) != NULL) {
173 have_port = false;
174 } else {
175 return false;
176 }
792beadc 177 } else {
5957a4c9
AJ
178 if ((e = strchr(s, ':')) != NULL) {
179 have_port = true;
180 } else if ((e = strchr(s, '/')) != NULL) {
181 have_port = false;
182 } else {
183 return false;
184 }
185 len = e - s;
d81a31f1
AR
186 }
187
d81a31f1
AR
188 host.limitInit(s, len);
189 s = e;
190
26ac0430 191 port = -1;
d81a31f1
AR
192 if (have_port) {
193 s++;
194
195 if ((e = strchr(s, '/')) != NULL) {
196 char *t;
26ac0430 197 const unsigned long p = strtoul(s, &t, 0);
d81a31f1 198
26ac0430
AJ
199 if (p > 65535) // port value is too high
200 return false;
d81a31f1
AR
201
202 port = static_cast<int>(p);
203
204 if (t != e) // extras after the port
205 return false;
206
207 s = e;
208
209 if (s[0] != '/')
210 return false;
211 }
212 }
213
214 // if no port, the caller may use service_configConfigs or supply the default if neeeded
215
216 s++;
217 e = strchr(s, '\0');
218 len = e - s;
219
220 if (len > 1024) {
221 debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
26ac0430 222 "long resource name (>1024), probably wrong");
d81a31f1
AR
223 }
224
225 resource.limitInit(s, len + 1);
a22e6cd3
AR
226 return true;
227}
228
d81a31f1 229
a22e6cd3
AR
230bool
231Adaptation::ServiceConfig::grokBool(bool &var, const char *name, const char *value)
232{
233 if (!strcmp(value, "0") || !strcmp(value, "off"))
234 var = false;
e1381638 235 else if (!strcmp(value, "1") || !strcmp(value, "on"))
a22e6cd3
AR
236 var = true;
237 else {
d81a31f1 238 debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
a22e6cd3
AR
239 "wrong value for boolean " << name << "; " <<
240 "'0', '1', 'on', or 'off' expected but got: " << value);
d81a31f1
AR
241 return false;
242 }
243
244 return true;
245}