]> git.ipfire.org Git - thirdparty/squid.git/blame - src/adaptation/ServiceConfig.cc
SourceFormat: enforcement
[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():
e1381638
AJ
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);
e1381638 94 else if (strcmp(name, "routing") == 0)
a22e6cd3
AR
95 grokked = grokBool(routing, name, value);
96 else {
97 debugs(3, 0, cfg_filename << ':' << config_lineno << ": " <<
e1381638 98 "unknown adaptation service option: " << name << '=' << value);
a22e6cd3
AR
99 }
100 if (!grokked)
101 return false;
102 }
103
104 // what is left must be the service URI
105 if (!grokUri(lastOption))
106 return false;
107
108 // there should be nothing else left
109 if (const char *tail = strtok(NULL, w_space)) {
110 debugs(3, 0, cfg_filename << ':' << config_lineno << ": " <<
e1381638 111 "garbage after adaptation service URI: " << tail);
a22e6cd3
AR
112 return false;
113 }
d81a31f1 114
a22e6cd3 115 debugs(3,5, cfg_filename << ':' << config_lineno << ": " <<
e1381638
AJ
116 "adaptation_service " << key << ' ' <<
117 methodStr() << "_" << vectPointStr() << ' ' <<
118 bypass << routing << ' ' <<
119 uri);
a22e6cd3
AR
120
121 return true;
122}
123
124bool
125Adaptation::ServiceConfig::grokUri(const char *value)
126{
d81a31f1
AR
127 // TODO: find core code that parses URLs and extracts various parts
128
a22e6cd3
AR
129 if (!value || !*value) {
130 debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
131 "empty adaptation service URI");
132 return false;
133 }
134
135 uri = value;
136
d81a31f1
AR
137 // extract scheme and use it as the service_configConfig protocol
138 const char *schemeSuffix = "://";
a22e6cd3
AR
139 const String::size_type schemeEnd = uri.find(schemeSuffix);
140 if (schemeEnd != String::npos)
b2f458b7 141 protocol=uri.substr(0,schemeEnd);
826a1fed 142
26ac0430
AJ
143 debugs(3, 5, HERE << cfg_filename << ':' << config_lineno << ": " <<
144 "service protocol is " << protocol);
826a1fed
FC
145
146 if (protocol.size() == 0)
26ac0430 147 return false;
d81a31f1
AR
148
149 // skip scheme
c1945e7d 150 const char *s = uri.termedBuf() + protocol.size() + strlen(schemeSuffix);
d81a31f1
AR
151
152 const char *e;
153
154 bool have_port = false;
155
156 if ((e = strchr(s, ':')) != NULL) {
157 have_port = true;
158 } else if ((e = strchr(s, '/')) != NULL) {
159 have_port = false;
160 } else {
161 return false;
162 }
163
164 int len = e - s;
165 host.limitInit(s, len);
166 s = e;
167
26ac0430 168 port = -1;
d81a31f1
AR
169 if (have_port) {
170 s++;
171
172 if ((e = strchr(s, '/')) != NULL) {
173 char *t;
26ac0430 174 const unsigned long p = strtoul(s, &t, 0);
d81a31f1 175
26ac0430
AJ
176 if (p > 65535) // port value is too high
177 return false;
d81a31f1
AR
178
179 port = static_cast<int>(p);
180
181 if (t != e) // extras after the port
182 return false;
183
184 s = e;
185
186 if (s[0] != '/')
187 return false;
188 }
189 }
190
191 // if no port, the caller may use service_configConfigs or supply the default if neeeded
192
193 s++;
194 e = strchr(s, '\0');
195 len = e - s;
196
197 if (len > 1024) {
198 debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
26ac0430 199 "long resource name (>1024), probably wrong");
d81a31f1
AR
200 }
201
202 resource.limitInit(s, len + 1);
a22e6cd3
AR
203 return true;
204}
205
d81a31f1 206
a22e6cd3
AR
207bool
208Adaptation::ServiceConfig::grokBool(bool &var, const char *name, const char *value)
209{
210 if (!strcmp(value, "0") || !strcmp(value, "off"))
211 var = false;
e1381638 212 else if (!strcmp(value, "1") || !strcmp(value, "on"))
a22e6cd3
AR
213 var = true;
214 else {
d81a31f1 215 debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
a22e6cd3
AR
216 "wrong value for boolean " << name << "; " <<
217 "'0', '1', 'on', or 'off' expected but got: " << value);
d81a31f1
AR
218 return false;
219 }
220
221 return true;
222}