]> git.ipfire.org Git - thirdparty/squid.git/blame - src/adaptation/icap/Options.cc
Revert r14137 due to compile errors
[thirdparty/squid.git] / src / adaptation / icap / Options.cc
CommitLineData
bbc27441 1/*
bde978a6 2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
bbc27441
AJ
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
582c2af2 9#include "squid.h"
26cc52cb 10#include "adaptation/icap/Config.h"
3d93a84d
AJ
11#include "adaptation/icap/Options.h"
12#include "base/TextException.h"
13#include "HttpReply.h"
985c86bc 14#include "SquidTime.h"
28204b3b 15#include "StrList.h"
3d93a84d 16#include "wordlist.h"
78e8cfc4 17
23541b3e 18Adaptation::Icap::Options::Options() :
f53969cc
SM
19 error("unconfigured"),
20 max_connections(-1),
21 allow204(false),
22 allow206(false),
23 preview(-1),
24 theTTL(-1),
25 theTimestamp(0)
774c051c 26{
c99de607 27 theTransfers.preview.name = "Transfer-Preview";
28 theTransfers.preview.kind = xferPreview;
29 theTransfers.ignore.name = "Transfer-Ignore";
30 theTransfers.ignore.kind = xferIgnore;
31 theTransfers.complete.name = "Transfer-Complete";
32 theTransfers.complete.kind = xferComplete;
33
34 // Section 4.10.2 of RFC 3507 says that default is no Preview
35 // TODO: provide a squid.conf option to overwrite the default
36 theTransfers.byDefault = &theTransfers.complete;
37}
774c051c 38
26cc52cb 39Adaptation::Icap::Options::~Options()
774c051c 40{
774c051c 41}
42
c99de607 43// future optimization note: this method is called by ICAP ACL code at least
44// twice for each HTTP message to see if the message should be ignored. For any
45// non-ignored HTTP message, ICAP calls to check whether a preview is needed.
26cc52cb 46Adaptation::Icap::Options::TransferKind Adaptation::Icap::Options::transferKind(const String &urlPath) const
774c051c 47{
c99de607 48 if (theTransfers.preview.matches(urlPath))
49 return xferPreview;
774c051c 50
c99de607 51 if (theTransfers.complete.matches(urlPath))
52 return xferComplete;
774c051c 53
c99de607 54 if (theTransfers.ignore.matches(urlPath))
55 return xferIgnore;
774c051c 56
192378eb 57 debugs(93,7, HERE << "url " << urlPath << " matches no extensions; " <<
9e008dda 58 "using default: " << theTransfers.byDefault->name);
c99de607 59 return theTransfers.byDefault->kind;
774c051c 60}
61
26cc52cb 62bool Adaptation::Icap::Options::valid() const
774c051c 63{
64 return !error;
65}
66
26cc52cb 67bool Adaptation::Icap::Options::fresh() const
774c051c 68{
69 return squid_curtime <= expire();
70}
71
26cc52cb 72int Adaptation::Icap::Options::ttl() const
5f8252d2 73{
74 Must(valid());
26cc52cb 75 return theTTL >= 0 ? theTTL : TheConfig.default_options_ttl;
5f8252d2 76}
77
26cc52cb 78time_t Adaptation::Icap::Options::expire() const
774c051c 79{
80 Must(valid());
5f8252d2 81 return theTimestamp + ttl();
774c051c 82}
83
26cc52cb 84void Adaptation::Icap::Options::configure(const HttpReply *reply)
774c051c 85{
86 error = NULL; // reset initial "unconfigured" value (or an old error?)
87
88 const HttpHeader *h = &reply->header;
89
9b769c67 90 if (reply->sline.status() != Http::scOkay)
774c051c 91 error = "unsupported status code of OPTIONS response";
92
93 // Methods
a9925b40 94 if (h->hasByNameListMember("Methods", "REQMOD", ','))
774c051c 95 cfgMethod(ICAP::methodReqmod);
96
a9925b40 97 if (h->hasByNameListMember("Methods", "RESPMOD", ','))
774c051c 98 cfgMethod(ICAP::methodRespmod);
99
a9925b40 100 service = h->getByName("Service");
774c051c 101
a9925b40 102 serviceId = h->getByName("ServiceId");
774c051c 103
a9925b40 104 istag = h->getByName("ISTag");
774c051c 105
40bb9887
AR
106 if (h->getByName("Opt-body-type").size()) {
107 // TODO: add a class to rate-limit such warnings using FadingCounter
108 debugs(93,DBG_IMPORTANT, "WARNING: Ignoring unsupported ICAP " <<
ab745b44 109 "OPTIONS body; type: " << h->getByName("Opt-body-type"));
40bb9887
AR
110 // Do not set error, assuming the response headers are valid.
111 }
774c051c 112
113 cfgIntHeader(h, "Max-Connections", max_connections);
2dba5b8e
CT
114 if (max_connections == 0)
115 debugs(93, DBG_IMPORTANT, "WARNING: Max-Connections is set to zero! ");
774c051c 116
8eeb99bf 117 cfgIntHeader(h, "Options-TTL", theTTL);
774c051c 118
a9925b40 119 theTimestamp = h->getTime(HDR_DATE);
774c051c 120
8eeb99bf 121 if (theTimestamp < 0)
122 theTimestamp = squid_curtime;
774c051c 123
a9925b40 124 if (h->hasListMember(HDR_ALLOW, "204", ','))
774c051c 125 allow204 = true;
126
83c51da9
CT
127 if (h->hasListMember(HDR_ALLOW, "206", ','))
128 allow206 = true;
129
774c051c 130 cfgIntHeader(h, "Preview", preview);
131
c99de607 132 cfgTransferList(h, theTransfers.preview);
133 cfgTransferList(h, theTransfers.ignore);
134 cfgTransferList(h, theTransfers.complete);
774c051c 135}
136
26cc52cb 137void Adaptation::Icap::Options::cfgMethod(ICAP::Method m)
774c051c 138{
139 Must(m != ICAP::methodNone);
4c9eadc2 140 methods.push_back(m);
774c051c 141}
142
143// TODO: HttpHeader should provide a general method for this type of conversion
26cc52cb 144void Adaptation::Icap::Options::cfgIntHeader(const HttpHeader *h, const char *fname, int &value)
774c051c 145{
30abd221 146 const String s = h->getByName(fname);
774c051c 147
5b4117d8
FC
148 if (s.size() && xisdigit(*s.termedBuf()))
149 value = atoi(s.termedBuf());
774c051c 150 else
151 value = -1;
c99de607 152
192378eb 153 debugs(93,5, HERE << "int header: " << fname << ": " << value);
c99de607 154}
155
26cc52cb 156void Adaptation::Icap::Options::cfgTransferList(const HttpHeader *h, TransferList &list)
c99de607 157{
30abd221 158 const String buf = h->getByName(list.name);
c99de607 159 bool foundStar = false;
160 list.parse(buf, foundStar);
161
162 if (foundStar) {
163 theTransfers.byDefault = &list;
192378eb 164 debugs(93,5, HERE << "set default transfer to " << list.name);
c99de607 165 }
166
26cc52cb 167 list.report(5, "Adaptation::Icap::Options::cfgTransferList: ");
c99de607 168}
169
26cc52cb 170/* Adaptation::Icap::Options::TransferList */
c99de607 171
26cc52cb 172Adaptation::Icap::Options::TransferList::TransferList(): extensions(NULL), name(NULL),
f53969cc 173 kind(xferNone)
9e008dda 174{
c99de607 175};
176
26cc52cb 177Adaptation::Icap::Options::TransferList::~TransferList()
9e008dda 178{
c99de607 179 wordlistDestroy(&extensions);
180};
181
26cc52cb 182void Adaptation::Icap::Options::TransferList::add(const char *extension)
9e008dda 183{
c99de607 184 wordlistAdd(&extensions, extension);
185};
186
26cc52cb 187bool Adaptation::Icap::Options::TransferList::matches(const String &urlPath) const
9e008dda 188{
c99de607 189 const int urlLen = urlPath.size();
190 for (wordlist *e = extensions; e; e = e->next) {
191 // optimize: store extension lengths
192 const int eLen = strlen(e->key);
193
194 // assume URL contains at least '/' before the extension
195 if (eLen < urlLen) {
196 const int eOff = urlLen - eLen;
197 // RFC 3507 examples imply that extensions come without leading '.'
5b4117d8
FC
198 if (urlPath[eOff-1] == '.' &&
199 strcmp(urlPath.termedBuf() + eOff, e->key) == 0) {
192378eb 200 debugs(93,7, HERE << "url " << urlPath << " matches " <<
9e008dda 201 name << " extension " << e->key);
c99de607 202 return true;
203 }
204 }
205 }
192378eb 206 debugs(93,8, HERE << "url " << urlPath << " matches no " << name << " extensions");
c99de607 207 return false;
208}
209
26cc52cb 210void Adaptation::Icap::Options::TransferList::parse(const String &buf, bool &foundStar)
9e008dda 211{
c99de607 212 foundStar = false;
213
214 const char *item;
215 const char *pos = NULL;
216 int ilen;
217 while (strListGetItem(&buf, ',', &item, &ilen, &pos)) {
218 if (ilen == 1 && *item == '*')
219 foundStar = true;
5c6dae44
AJ
220 else {
221 const char *tmp = xstrndup(item, ilen+1);
222 add(tmp);
223 xfree(tmp);
224 }
c99de607 225 }
226}
227
26cc52cb 228void Adaptation::Icap::Options::TransferList::report(int level, const char *prefix) const
9e008dda 229{
c99de607 230 if (extensions) {
231 for (wordlist *e = extensions; e; e = e->next)
232 debugs(93,level, prefix << name << ": " << e->key);
233 } else {
234 debugs(93,level, prefix << "no " << name << " extensions");
235 }
774c051c 236}
f53969cc 237