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