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