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