]>
Commit | Line | Data |
---|---|---|
d81a31f1 AR |
1 | /* |
2 | * DEBUG: section XXX | |
3 | */ | |
4 | ||
5 | #include "squid.h" | |
6 | #include "ConfigParser.h" | |
7 | #include "adaptation/ServiceConfig.h" | |
8 | ||
26ac0430 | 9 | Adaptation::ServiceConfig::ServiceConfig(): |
e1381638 AJ |
10 | port(-1), method(methodNone), point(pointNone), |
11 | bypass(false), routing(false) | |
d81a31f1 AR |
12 | {} |
13 | ||
14 | const char * | |
15 | Adaptation::ServiceConfig::methodStr() const | |
16 | { | |
17 | return Adaptation::methodStr(method); | |
18 | } | |
19 | ||
20 | const char * | |
21 | Adaptation::ServiceConfig::vectPointStr() const | |
22 | { | |
23 | return Adaptation::vectPointStr(point); | |
24 | } | |
25 | ||
26 | Adaptation::Method | |
27 | Adaptation::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 | ||
38 | Adaptation::VectPoint | |
39 | Adaptation::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 | ||
56 | bool | |
57 | Adaptation::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 | ||
124 | bool | |
125 | Adaptation::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 |
207 | bool |
208 | Adaptation::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 | } |