]> git.ipfire.org Git - thirdparty/squid.git/blame - src/adaptation/ecap/MessageRep.cc
Bug 4722: eCAP compile errors after v5 r15147
[thirdparty/squid.git] / src / adaptation / ecap / MessageRep.cc
CommitLineData
fdc96a39 1/*
4ac4a490 2 * Copyright (C) 1996-2017 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.
fdc96a39 7 */
bbc27441
AJ
8
9/* DEBUG: section 93 eCAP Interface */
10
582c2af2 11#include "squid.h"
cf331c99 12#include "BodyPipe.h"
602d9612
A
13#include "HttpReply.h"
14#include "HttpRequest.h"
cf331c99
AR
15#include <libecap/common/names.h>
16#include <libecap/common/area.h>
17#include <libecap/common/version.h>
12a410c3 18#include <libecap/common/named_values.h>
602d9612 19#include "adaptation/ecap/Host.h" /* for protocol constants */
1f3c65fc
AR
20#include "adaptation/ecap/MessageRep.h"
21#include "adaptation/ecap/XactionRep.h"
3d93a84d 22#include "base/TextException.h"
b1bd952a 23#include "URL.h"
fdc96a39 24
cf331c99
AR
25/* HeaderRep */
26
63df1d28 27Adaptation::Ecap::HeaderRep::HeaderRep(Http::Message &aMessage): theHeader(aMessage.header),
f53969cc 28 theMessage(aMessage)
cf331c99
AR
29{
30}
31
cf331c99 32bool
574b508c 33Adaptation::Ecap::HeaderRep::hasAny(const Name &name) const
cf331c99 34{
789217a2 35 const Http::HdrType squidId = TranslateHeaderId(name);
789217a2 36 return squidId == Http::HdrType::OTHER ?
6c28dd4a
SM
37 theHeader.hasNamed(name.image().c_str(), name.image().size()) :
38 static_cast<bool>(theHeader.has(squidId));
cf331c99
AR
39}
40
574b508c
AR
41Adaptation::Ecap::HeaderRep::Value
42Adaptation::Ecap::HeaderRep::value(const Name &name) const
cf331c99 43{
789217a2
FC
44 const Http::HdrType squidId = TranslateHeaderId(name);
45 const String value = squidId == Http::HdrType::OTHER ?
26ac0430
AJ
46 theHeader.getByName(name.image().c_str()) :
47 theHeader.getStrOrList(squidId);
b38b26cb 48 return value.size() > 0 ?
001eaf80 49 Value::FromTempString(value.termedBuf()) : Value();
cf331c99
AR
50}
51
52void
574b508c 53Adaptation::Ecap::HeaderRep::add(const Name &name, const Value &value)
cf331c99 54{
789217a2 55 const Http::HdrType squidId = TranslateHeaderId(name); // Http::HdrType::OTHER OK
3848295a 56 HttpHeaderEntry *e = new HttpHeaderEntry(squidId, SBuf(name.image()),
26ac0430 57 value.toString().c_str());
cf331c99 58 theHeader.addEntry(e);
809fd5d3 59
789217a2
FC
60 if (squidId == Http::HdrType::CONTENT_LENGTH)
61 theMessage.content_length = theHeader.getInt64(Http::HdrType::CONTENT_LENGTH);
cf331c99
AR
62}
63
64void
574b508c 65Adaptation::Ecap::HeaderRep::removeAny(const Name &name)
cf331c99 66{
789217a2
FC
67 const Http::HdrType squidId = TranslateHeaderId(name);
68 if (squidId == Http::HdrType::OTHER)
cf331c99
AR
69 theHeader.delByName(name.image().c_str());
70 else
71 theHeader.delById(squidId);
809fd5d3 72
789217a2
FC
73 if (squidId == Http::HdrType::CONTENT_LENGTH)
74 theMessage.content_length = theHeader.getInt64(Http::HdrType::CONTENT_LENGTH);
cf331c99
AR
75}
76
12a410c3
AR
77void
78Adaptation::Ecap::HeaderRep::visitEach(libecap::NamedValueVisitor &visitor) const
79{
80 HttpHeaderPos pos = HttpHeaderInitPos;
81 while (HttpHeaderEntry *e = theHeader.getEntry(&pos)) {
3848295a 82 const Name name(std::string(e->name.rawContent(), e->name.length())); // optimize: find std Names
12a410c3
AR
83 name.assignHostId(e->id);
84 visitor.visit(name, Value(e->value.rawBuf(), e->value.size()));
85 }
86}
87
cf331c99 88libecap::Area
574b508c 89Adaptation::Ecap::HeaderRep::image() const
cf331c99
AR
90{
91 MemBuf mb;
92 mb.init();
10201568 93 theMessage.packInto(&mb, true);
cf331c99
AR
94 return Area::FromTempBuffer(mb.content(), mb.contentSize());
95}
96
97// throws on failures
98void
574b508c 99Adaptation::Ecap::HeaderRep::parse(const Area &buf)
cf331c99 100{
955394ce 101 Http::StatusCode error;
9b491ddf 102 Must(theMessage.parse(buf.start, buf.size, true, &error));
cf331c99
AR
103}
104
789217a2 105Http::HdrType
574b508c 106Adaptation::Ecap::HeaderRep::TranslateHeaderId(const Name &name)
77773405
AR
107{
108 if (name.assignedHostId())
789217a2
FC
109 return static_cast<Http::HdrType>(name.hostId());
110 return Http::HdrType::OTHER;
77773405
AR
111}
112
77773405
AR
113/* FirstLineRep */
114
63df1d28 115Adaptation::Ecap::FirstLineRep::FirstLineRep(Http::Message &aMessage): theMessage(aMessage)
77773405
AR
116{
117}
118
cf331c99 119libecap::Version
574b508c 120Adaptation::Ecap::FirstLineRep::version() const
cf331c99
AR
121{
122 return libecap::Version(theMessage.http_ver.major,
26ac0430 123 theMessage.http_ver.minor);
cf331c99
AR
124}
125
126void
574b508c 127Adaptation::Ecap::FirstLineRep::version(const libecap::Version &aVersion)
cf331c99
AR
128{
129 theMessage.http_ver.major = aVersion.majr;
130 theMessage.http_ver.minor = aVersion.minr;
131}
132
133libecap::Name
574b508c 134Adaptation::Ecap::FirstLineRep::protocol() const
cf331c99
AR
135{
136 // TODO: optimize?
7b167513 137 switch (theMessage.http_ver.protocol) {
39a19cb7 138 case AnyP::PROTO_HTTP:
26ac0430 139 return libecap::protocolHttp;
39a19cb7 140 case AnyP::PROTO_HTTPS:
26ac0430 141 return libecap::protocolHttps;
39a19cb7 142 case AnyP::PROTO_FTP:
26ac0430 143 return libecap::protocolFtp;
39a19cb7 144 case AnyP::PROTO_GOPHER:
26ac0430 145 return libecap::protocolGopher;
39a19cb7 146 case AnyP::PROTO_WAIS:
26ac0430 147 return libecap::protocolWais;
39a19cb7 148 case AnyP::PROTO_WHOIS:
26ac0430 149 return libecap::protocolWhois;
39a19cb7 150 case AnyP::PROTO_URN:
26ac0430 151 return libecap::protocolUrn;
39a19cb7 152 case AnyP::PROTO_ICP:
26ac0430 153 return protocolIcp;
cf331c99 154#if USE_HTCP
39a19cb7 155 case AnyP::PROTO_HTCP:
26ac0430 156 return protocolHtcp;
cf331c99 157#endif
39a19cb7 158 case AnyP::PROTO_CACHE_OBJECT:
26ac0430 159 return protocolCacheObj;
39a19cb7 160 case AnyP::PROTO_ICY:
555aedbf 161 return protocolIcy;
a90ea541
AJ
162 case AnyP::PROTO_COAP:
163 case AnyP::PROTO_COAPS: // use 'unknown' until libecap supports coap:// and coaps://
3848295a
AJ
164 // other protocols defined in Squid but not libecap use 'unknown'
165 case AnyP::PROTO_AUTHORITY_FORM:
166 case AnyP::PROTO_SSL:
167 case AnyP::PROTO_TLS:
555aedbf
AR
168 case AnyP::PROTO_UNKNOWN:
169 return protocolUnknown; // until we remember the protocol image
39a19cb7 170 case AnyP::PROTO_NONE:
26ac0430
AJ
171 return Name();
172
39a19cb7 173 case AnyP::PROTO_MAX:
26ac0430 174 break; // should not happen
39a19cb7 175 // no default to catch AnyP::PROTO_ additions
cf331c99
AR
176 }
177 Must(false); // not reached
178 return Name();
179}
180
181void
574b508c 182Adaptation::Ecap::FirstLineRep::protocol(const Name &p)
cf331c99
AR
183{
184 // TODO: what happens if we fail to translate some protocol?
7b167513 185 theMessage.http_ver.protocol = TranslateProtocolId(p);
cf331c99
AR
186}
187
555aedbf 188AnyP::ProtocolType
574b508c 189Adaptation::Ecap::FirstLineRep::TranslateProtocolId(const Name &name)
77773405
AR
190{
191 if (name.assignedHostId())
555aedbf
AR
192 return static_cast<AnyP::ProtocolType>(name.hostId());
193 return AnyP::PROTO_UNKNOWN;
77773405
AR
194}
195
cf331c99
AR
196/* RequestHeaderRep */
197
574b508c 198Adaptation::Ecap::RequestLineRep::RequestLineRep(HttpRequest &aMessage):
f53969cc 199 FirstLineRep(aMessage), theMessage(aMessage)
cf331c99
AR
200{
201}
202
203void
574b508c 204Adaptation::Ecap::RequestLineRep::uri(const Area &aUri)
cf331c99
AR
205{
206 // TODO: if method is not set, urlPath will assume it is not connect;
207 // Can we change urlParse API to remove the method parameter?
208 // TODO: optimize: urlPath should take constant URL buffer
209 char *buf = xstrdup(aUri.toString().c_str());
210 const bool ok = urlParse(theMessage.method, buf, &theMessage);
211 xfree(buf);
212 Must(ok);
213}
214
574b508c
AR
215Adaptation::Ecap::RequestLineRep::Area
216Adaptation::Ecap::RequestLineRep::uri() const
cf331c99 217{
851feda6
AJ
218 const SBuf &fullUrl = theMessage.effectiveRequestUri();
219 // XXX: effectiveRequestUri() cannot return NULL or even empty string, some other problem?
220 Must(!fullUrl.isEmpty());
dd31ab8f 221 // optimize: avoid copying by having an Area::Detail that locks theMessage
851feda6 222 return Area::FromTempBuffer(fullUrl.rawContent(), fullUrl.length());
cf331c99
AR
223}
224
225void
574b508c 226Adaptation::Ecap::RequestLineRep::method(const Name &aMethod)
cf331c99
AR
227{
228 if (aMethod.assignedHostId()) {
229 const int id = aMethod.hostId();
23ef3d70
FC
230 Must(Http::METHOD_NONE < id && id < Http::METHOD_ENUM_END);
231 Must(id != Http::METHOD_OTHER);
c2a7cefd 232 theMessage.method = HttpRequestMethod(static_cast<Http::MethodType>(id));
cf331c99
AR
233 } else {
234 const std::string &image = aMethod.image();
f42a67c5 235 theMessage.method.HttpRequestMethodXXX(image.c_str());
cf331c99
AR
236 }
237}
238
574b508c
AR
239Adaptation::Ecap::RequestLineRep::Name
240Adaptation::Ecap::RequestLineRep::method() const
cf331c99
AR
241{
242 switch (theMessage.method.id()) {
23ef3d70 243 case Http::METHOD_GET:
26ac0430 244 return libecap::methodGet;
23ef3d70 245 case Http::METHOD_POST:
26ac0430 246 return libecap::methodPost;
23ef3d70 247 case Http::METHOD_PUT:
26ac0430 248 return libecap::methodPut;
23ef3d70 249 case Http::METHOD_HEAD:
26ac0430 250 return libecap::methodHead;
23ef3d70 251 case Http::METHOD_CONNECT:
26ac0430 252 return libecap::methodConnect;
23ef3d70 253 case Http::METHOD_DELETE:
26ac0430 254 return libecap::methodDelete;
23ef3d70 255 case Http::METHOD_TRACE:
26ac0430
AJ
256 return libecap::methodTrace;
257 default:
e44adabd 258 return Name(theMessage.method.image().toStdString());
cf331c99
AR
259 }
260}
261
77773405 262libecap::Version
574b508c 263Adaptation::Ecap::RequestLineRep::version() const
77773405
AR
264{
265 return FirstLineRep::version();
266}
267
268void
574b508c 269Adaptation::Ecap::RequestLineRep::version(const libecap::Version &aVersion)
77773405
AR
270{
271 FirstLineRep::version(aVersion);
272}
273
274libecap::Name
574b508c 275Adaptation::Ecap::RequestLineRep::protocol() const
77773405
AR
276{
277 return FirstLineRep::protocol();
278}
279
280void
574b508c 281Adaptation::Ecap::RequestLineRep::protocol(const Name &p)
77773405
AR
282{
283 FirstLineRep::protocol(p);
284}
285
cf331c99
AR
286/* ReplyHeaderRep */
287
574b508c 288Adaptation::Ecap::StatusLineRep::StatusLineRep(HttpReply &aMessage):
f53969cc 289 FirstLineRep(aMessage), theMessage(aMessage)
cf331c99
AR
290{
291}
292
293void
574b508c 294Adaptation::Ecap::StatusLineRep::statusCode(int code)
cf331c99 295{
3ca77494 296 theMessage.sline.set(theMessage.sline.version, static_cast<Http::StatusCode>(code), nullptr);
cf331c99
AR
297}
298
299int
574b508c 300Adaptation::Ecap::StatusLineRep::statusCode() const
cf331c99 301{
9b769c67
AJ
302 // TODO: remove cast when possible
303 return static_cast<int>(theMessage.sline.status());
cf331c99
AR
304}
305
306void
65b0aca4 307Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area &)
cf331c99 308{
65b0aca4
AR
309 // Squid does not support external custom reason phrases so we have
310 // to just reset it (in case there was a custom internal reason set)
311 theMessage.sline.resetReason();
cf331c99
AR
312}
313
574b508c
AR
314Adaptation::Ecap::StatusLineRep::Area
315Adaptation::Ecap::StatusLineRep::reasonPhrase() const
cf331c99 316{
9b769c67 317 return Area::FromTempString(std::string(theMessage.sline.reason()));
cf331c99
AR
318}
319
77773405 320libecap::Version
574b508c 321Adaptation::Ecap::StatusLineRep::version() const
77773405
AR
322{
323 return FirstLineRep::version();
324}
325
326void
574b508c 327Adaptation::Ecap::StatusLineRep::version(const libecap::Version &aVersion)
77773405
AR
328{
329 FirstLineRep::version(aVersion);
330}
331
332libecap::Name
574b508c 333Adaptation::Ecap::StatusLineRep::protocol() const
77773405
AR
334{
335 return FirstLineRep::protocol();
336}
337
338void
574b508c 339Adaptation::Ecap::StatusLineRep::protocol(const Name &p)
77773405
AR
340{
341 FirstLineRep::protocol(p);
342}
cf331c99
AR
343
344/* BodyRep */
345
574b508c 346Adaptation::Ecap::BodyRep::BodyRep(const BodyPipe::Pointer &aBody): theBody(aBody)
cf331c99
AR
347{
348}
349
77773405 350void
574b508c 351Adaptation::Ecap::BodyRep::tie(const BodyPipe::Pointer &aBody)
77773405
AR
352{
353 Must(!theBody);
354 Must(aBody != NULL);
355 theBody = aBody;
356}
357
574b508c
AR
358Adaptation::Ecap::BodyRep::BodySize
359Adaptation::Ecap::BodyRep::bodySize() const
cf331c99 360{
e4a88e44 361 return (theBody != nullptr && theBody->bodySizeKnown()) ? BodySize(theBody->bodySize()) : BodySize();
cf331c99
AR
362}
363
cf331c99
AR
364/* MessageRep */
365
63df1d28 366Adaptation::Ecap::MessageRep::MessageRep(Http::Message *rawHeader):
f53969cc
SM
367 theMessage(rawHeader), theFirstLineRep(NULL),
368 theHeaderRep(NULL), theBodyRep(NULL)
cf331c99
AR
369{
370 Must(theMessage.header); // we do not want to represent a missing message
371
372 if (HttpRequest *req = dynamic_cast<HttpRequest*>(theMessage.header))
77773405 373 theFirstLineRep = new RequestLineRep(*req);
e1381638
AJ
374 else if (HttpReply *rep = dynamic_cast<HttpReply*>(theMessage.header))
375 theFirstLineRep = new StatusLineRep(*rep);
cf331c99 376 else
e1381638 377 Must(false); // unknown message header type
cf331c99 378
77773405
AR
379 theHeaderRep = new HeaderRep(*theMessage.header);
380
cf331c99
AR
381 if (theMessage.body_pipe != NULL)
382 theBodyRep = new BodyRep(theMessage.body_pipe);
383}
384
574b508c 385Adaptation::Ecap::MessageRep::~MessageRep()
cf331c99 386{
77773405 387 delete theBodyRep;
80031342
AR
388 delete theHeaderRep;
389 delete theFirstLineRep;
77773405
AR
390}
391
392libecap::shared_ptr<libecap::Message>
574b508c 393Adaptation::Ecap::MessageRep::clone() const
77773405 394{
63df1d28 395 Http::Message *hdr = theMessage.header->clone();
77773405
AR
396 hdr->body_pipe = NULL; // if any; TODO: remove pipe cloning from ::clone?
397 libecap::shared_ptr<libecap::Message> res(new MessageRep(hdr));
398
399 // restore indication of a body if needed, but not the pipe
400 if (theMessage.header->body_pipe != NULL)
401 res->addBody();
402
403 return res;
404}
405
406libecap::FirstLine &
574b508c 407Adaptation::Ecap::MessageRep::firstLine()
77773405
AR
408{
409 return *theFirstLineRep;
410}
411
412const libecap::FirstLine &
574b508c 413Adaptation::Ecap::MessageRep::firstLine() const
77773405
AR
414{
415 return *theFirstLineRep;
cf331c99
AR
416}
417
418libecap::Header &
574b508c 419Adaptation::Ecap::MessageRep::header()
cf331c99
AR
420{
421 return *theHeaderRep;
422}
423
424const libecap::Header &
574b508c 425Adaptation::Ecap::MessageRep::header() const
cf331c99
AR
426{
427 return *theHeaderRep;
428}
429
430libecap::Body *
574b508c 431Adaptation::Ecap::MessageRep::body()
cf331c99
AR
432{
433 return theBodyRep;
434}
435
436void
574b508c 437Adaptation::Ecap::MessageRep::addBody()
cf331c99 438{
cf331c99 439 Must(!theBodyRep);
77773405
AR
440 Must(!theMessage.body_pipe); // set in tieBody()
441 theBodyRep = new BodyRep(NULL);
442}
443
444void
574b508c 445Adaptation::Ecap::MessageRep::tieBody(Adaptation::Ecap::XactionRep *x)
77773405
AR
446{
447 Must(theBodyRep != NULL); // addBody must be called first
ce367911 448 Must(!theMessage.header->body_pipe);
cf331c99 449 Must(!theMessage.body_pipe);
ce367911
AR
450 theMessage.header->body_pipe = new BodyPipe(x);
451 theMessage.body_pipe = theMessage.header->body_pipe;
77773405 452 theBodyRep->tie(theMessage.body_pipe);
cf331c99
AR
453}
454
574b508c 455const libecap::Body *Adaptation::Ecap::MessageRep::body() const
cf331c99
AR
456{
457 return theBodyRep;
458}
f53969cc 459