]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/Config.cc
9fc5fe978326f515adb9c7fabc02c01f5ff04570
[thirdparty/squid.git] / src / adaptation / Config.cc
1
2 /*
3 * $Id$
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 */
32
33 #include "squid.h"
34 #include "acl/FilledChecklist.h"
35 #include "acl/Gadgets.h"
36 #include "adaptation/AccessRule.h"
37 #include "adaptation/Config.h"
38 #include "adaptation/History.h"
39 #include "adaptation/Service.h"
40 #include "adaptation/ServiceGroups.h"
41 #include "Array.h"
42 #include "ConfigParser.h"
43 #include "globals.h"
44 #include "HttpReply.h"
45 #include "HttpRequest.h"
46 #include "Store.h"
47 #include "structs.h"
48
49 bool Adaptation::Config::Enabled = false;
50 char *Adaptation::Config::masterx_shared_name = NULL;
51 int Adaptation::Config::service_iteration_limit = 16;
52 int Adaptation::Config::send_client_ip = false;
53 int Adaptation::Config::send_username = false;
54 int Adaptation::Config::use_indirect_client = true;
55 Adaptation::Config::MetaHeaders Adaptation::Config::metaHeaders;
56
57
58 Adaptation::Config::MetaHeader::Value::~Value()
59 {
60 aclDestroyAclList(&aclList);
61 }
62
63 Adaptation::Config::MetaHeader::Value::Pointer
64 Adaptation::Config::MetaHeader::addValue(const String &value)
65 {
66 Value::Pointer v = new Value(value);
67 values.push_back(v);
68 return v;
69 }
70
71 const char *
72 Adaptation::Config::MetaHeader::match(HttpRequest *request, HttpReply *reply)
73 {
74
75 typedef Values::iterator VLI;
76 ACLFilledChecklist ch(NULL, request, NULL);
77 if (reply)
78 ch.reply = HTTPMSGLOCK(reply);
79
80 for (VLI i = values.begin(); i != values.end(); ++i ) {
81 const int ret= ch.fastCheck((*i)->aclList);
82 debugs(93, 5, HERE << "Check for header name: " << name << ": " << (*i)->value
83 <<", HttpRequest: " << request << " HttpReply: " << reply << " matched: " << ret);
84 if (ret == ACCESS_ALLOWED)
85 return (*i)->value.termedBuf();
86 }
87 return NULL;
88 }
89
90 Adaptation::Config::MetaHeader::Pointer
91 Adaptation::Config::addMetaHeader(const String &headerName)
92 {
93 typedef MetaHeaders::iterator AMLI;
94 for (AMLI i = metaHeaders.begin(); i != metaHeaders.end(); ++i) {
95 if ((*i)->name == headerName)
96 return (*i);
97 }
98
99 MetaHeader::Pointer meta = new MetaHeader(headerName);
100 metaHeaders.push_back(meta);
101 return meta;
102 }
103
104
105 Adaptation::ServiceConfig*
106 Adaptation::Config::newServiceConfig() const
107 {
108 return new ServiceConfig();
109 }
110
111 void
112 Adaptation::Config::removeService(const String& service)
113 {
114 removeRule(service);
115 const Groups& groups = AllGroups();
116 for (unsigned int i = 0; i < groups.size(); ) {
117 const ServiceGroupPointer group = groups[i];
118 const ServiceGroup::Store& services = group->services;
119 typedef ServiceGroup::Store::const_iterator SGSI;
120 for (SGSI it = services.begin(); it != services.end(); ++it) {
121 if (*it == service) {
122 group->removedServices.push_back(service);
123 group->services.prune(service);
124 debugs(93, 5, HERE << "adaptation service " << service <<
125 " removed from group " << group->id);
126 break;
127 }
128 }
129 if (services.empty()) {
130 removeRule(group->id);
131 AllGroups().prune(group);
132 } else {
133 ++i;
134 }
135 }
136 }
137
138 void
139 Adaptation::Config::removeRule(const String& id)
140 {
141 typedef AccessRules::const_iterator ARI;
142 const AccessRules& rules = AllRules();
143 for (ARI it = rules.begin(); it != rules.end(); ++it) {
144 AccessRule* rule = *it;
145 if (rule->groupId == id) {
146 debugs(93, 5, HERE << "removing access rules for:" << id);
147 AllRules().prune(rule);
148 delete (rule);
149 break;
150 }
151 }
152 }
153
154 void
155 Adaptation::Config::clear()
156 {
157 debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " <<
158 AllGroups().size() << ", services: " << serviceConfigs.size());
159 typedef ServiceConfigs::const_iterator SCI;
160 const ServiceConfigs& configs = serviceConfigs;
161 for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg)
162 removeService((*cfg)->key);
163 serviceConfigs.clean();
164 debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " <<
165 AllGroups().size() << ", services: " << serviceConfigs.size());
166 }
167
168 void
169 Adaptation::Config::parseService()
170 {
171 ServiceConfigPointer cfg = newServiceConfig();
172 if (!cfg->parse()) {
173 fatalf("%s:%d: malformed adaptation service configuration",
174 cfg_filename, config_lineno);
175 }
176 serviceConfigs.push_back(cfg);
177 }
178
179 void
180 Adaptation::Config::freeService()
181 {
182 FreeAccess();
183 FreeServiceGroups();
184
185 DetachServices();
186
187 serviceConfigs.clean();
188
189 FreeMetaHeader();
190 }
191
192 void
193 Adaptation::Config::dumpService(StoreEntry *entry, const char *name) const
194 {
195 typedef Services::iterator SCI;
196 for (SCI i = AllServices().begin(); i != AllServices().end(); ++i) {
197 const ServiceConfig &cfg = (*i)->cfg();
198 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "_%s %s %d " SQUIDSTRINGPH "\n",
199 name,
200 SQUIDSTRINGPRINT(cfg.key),
201 cfg.methodStr(), cfg.vectPointStr(), cfg.bypass,
202 SQUIDSTRINGPRINT(cfg.uri));
203 }
204 }
205
206 bool
207 Adaptation::Config::finalize()
208 {
209 if (!onoff) {
210 clear();
211 return false;
212 }
213
214 // create service reps from service configs
215 int created = 0;
216
217 typedef ServiceConfigs::const_iterator VISCI;
218 const ServiceConfigs &configs = serviceConfigs;
219 for (VISCI i = configs.begin(); i != configs.end(); ++i) {
220 const ServiceConfigPointer cfg = *i;
221 if (FindService(cfg->key) != NULL) {
222 debugs(93, DBG_CRITICAL, "ERROR: Duplicate adaptation service name: " <<
223 cfg->key);
224 continue; // TODO: make fatal
225 }
226 ServicePointer s = createService(cfg);
227 if (s != NULL) {
228 AllServices().push_back(s);
229 ++created;
230 }
231 }
232
233 debugs(93,3, HERE << "Created " << created << " adaptation services");
234
235 // services remember their configs; we do not have to
236 serviceConfigs.clean();
237 return true;
238 }
239
240 // poor man for_each
241 template <class Collection>
242 static void
243 FinalizeEach(Collection &collection, const char *label)
244 {
245 typedef typename Collection::iterator CI;
246 for (CI i = collection.begin(); i != collection.end(); ++i)
247 (*i)->finalize();
248
249 debugs(93,2, HERE << "Initialized " << collection.size() << ' ' << label);
250 }
251
252 void
253 Adaptation::Config::Finalize(bool enabled)
254 {
255 Enabled = enabled;
256 debugs(93, DBG_IMPORTANT, "Adaptation support is " << (Enabled ? "on" : "off."));
257
258 FinalizeEach(AllServices(), "message adaptation services");
259 FinalizeEach(AllGroups(), "message adaptation service groups");
260 FinalizeEach(AllRules(), "message adaptation access rules");
261 }
262
263 void
264 Adaptation::Config::ParseMetaHeader(ConfigParser &parser)
265 {
266 String name, value;
267 const char *warnFor[] = {
268 "Methods",
269 "Service",
270 "ISTag",
271 "Encapsulated",
272 "Opt-body-type",
273 "Max-Connections",
274 "Options-TTL",
275 "Date",
276 "Service-ID",
277 "Allow",
278 "Preview",
279 "Transfer-Preview",
280 "Transfer-Ignore",
281 "Transfer-Complete",
282 NULL
283 };
284 ConfigParser::ParseString(&name);
285 ConfigParser::ParseQuotedString(&value);
286
287 // TODO: Find a way to move this check to ICAP
288 for (int i = 0; warnFor[i] != NULL; ++i) {
289 if (name.caseCmp(warnFor[i]) == 0) {
290 fatalf("%s:%d: meta name \"%s\" is a reserved ICAP header name",
291 cfg_filename, config_lineno, name.termedBuf());
292 }
293 }
294
295 MetaHeader::Pointer meta = addMetaHeader(name);
296 MetaHeader::Value::Pointer headValue = meta->addValue(value);
297 aclParseAclList(parser, &headValue->aclList);
298 }
299
300 void
301 Adaptation::Config::DumpMetaHeader(StoreEntry *entry, const char *name)
302 {
303 typedef MetaHeaders::iterator AMLI;
304 for (AMLI m = metaHeaders.begin(); m != metaHeaders.end(); ++m) {
305 typedef MetaHeader::Values::iterator VLI;
306 for (VLI v =(*m)->values.begin(); v != (*m)->values.end(); ++v ) {
307 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH " %s",
308 name, SQUIDSTRINGPRINT((*m)->name), ConfigParser::QuoteString((*v)->value));
309 dump_acl_list(entry, (*v)->aclList);
310 storeAppendPrintf(entry, "\n");
311 }
312 }
313 }
314
315 void
316 Adaptation::Config::FreeMetaHeader()
317 {
318 metaHeaders.clean();
319 }
320
321 void
322 Adaptation::Config::ParseServiceSet()
323 {
324 Adaptation::Config::ParseServiceGroup(new ServiceSet);
325 }
326
327 void
328 Adaptation::Config::ParseServiceChain()
329 {
330 Adaptation::Config::ParseServiceGroup(new ServiceChain);
331 }
332
333 void
334 Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g)
335 {
336 assert(g != NULL);
337 g->parse();
338 AllGroups().push_back(g);
339 }
340
341 void
342 Adaptation::Config::FreeServiceGroups()
343 {
344 while (!AllGroups().empty()) {
345 // groups are refcounted so we do not explicitly delete them
346 AllGroups().pop_back();
347 }
348 }
349
350 void
351 Adaptation::Config::DumpServiceGroups(StoreEntry *entry, const char *name)
352 {
353 typedef Groups::iterator GI;
354 for (GI i = AllGroups().begin(); i != AllGroups().end(); ++i)
355 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "\n", name, SQUIDSTRINGPRINT((*i)->id));
356 }
357
358 void
359 Adaptation::Config::ParseAccess(ConfigParser &parser)
360 {
361 String groupId;
362 ConfigParser::ParseString(&groupId);
363 AccessRule *r;
364 if (!(r=FindRuleByGroupId(groupId))) {
365 r = new AccessRule(groupId);
366 AllRules().push_back(r);
367 }
368 r->parse(parser);
369 }
370
371 void
372 Adaptation::Config::FreeAccess()
373 {
374 while (!AllRules().empty()) {
375 delete AllRules().back();
376 AllRules().pop_back();
377 }
378 }
379
380 void
381 Adaptation::Config::DumpAccess(StoreEntry *entry, const char *name)
382 {
383 LOCAL_ARRAY(char, nom, 64);
384
385 typedef AccessRules::iterator CI;
386 for (CI i = AllRules().begin(); i != AllRules().end(); ++i) {
387 snprintf(nom, 64, "%s " SQUIDSTRINGPH, name, SQUIDSTRINGPRINT((*i)->groupId));
388 dump_acl_access(entry, nom, (*i)->acl);
389 }
390 }
391
392 Adaptation::Config::Config()
393 {
394 // XXX: should we init members?
395 }
396
397 // XXX: this is called for ICAP and eCAP configs, but deals mostly
398 // with global arrays shared by those individual configs
399 Adaptation::Config::~Config()
400 {
401 freeService();
402 }