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