source: squid-ssl/trunk/fuentes/src/adaptation/ServiceConfig.cc @ 5495

Last change on this file since 5495 was 5495, checked in by Juanma, 2 years ago

Initial release

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