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