]> git.ipfire.org Git - thirdparty/squid.git/blame - src/adaptation/ecap/MessageRep.cc
Renamed squid.h to squid-old.h and config.h to squid.h
[thirdparty/squid.git] / src / adaptation / ecap / MessageRep.cc
CommitLineData
fdc96a39 1/*
b510f3a1 2 * DEBUG: section 93 eCAP Interface
fdc96a39 3 */
f7f3304a 4#include "squid-old.h"
cf331c99
AR
5#include "HttpRequest.h"
6#include "HttpReply.h"
7#include "BodyPipe.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>
1f3c65fc
AR
12#include "adaptation/ecap/MessageRep.h"
13#include "adaptation/ecap/XactionRep.h"
14#include "adaptation/ecap/Host.h" /* for protocol constants */
3d93a84d 15#include "base/TextException.h"
fdc96a39 16
cf331c99
AR
17/* HeaderRep */
18
574b508c 19Adaptation::Ecap::HeaderRep::HeaderRep(HttpMsg &aMessage): theHeader(aMessage.header),
26ac0430 20 theMessage(aMessage)
cf331c99
AR
21{
22}
23
cf331c99 24bool
574b508c 25Adaptation::Ecap::HeaderRep::hasAny(const Name &name) const
cf331c99
AR
26{
27 const http_hdr_type squidId = TranslateHeaderId(name);
28 // XXX: optimize to remove getByName: we do not need the value here
29 return squidId == HDR_OTHER ?
26ac0430
AJ
30 theHeader.getByName(name.image().c_str()).size() > 0:
31 (bool)theHeader.has(squidId);
cf331c99
AR
32}
33
574b508c
AR
34Adaptation::Ecap::HeaderRep::Value
35Adaptation::Ecap::HeaderRep::value(const Name &name) const
cf331c99
AR
36{
37 const http_hdr_type squidId = TranslateHeaderId(name);
38 const String value = squidId == HDR_OTHER ?
26ac0430
AJ
39 theHeader.getByName(name.image().c_str()) :
40 theHeader.getStrOrList(squidId);
5e6f9b92 41 return value.defined() ?
001eaf80 42 Value::FromTempString(value.termedBuf()) : Value();
cf331c99
AR
43}
44
45void
574b508c 46Adaptation::Ecap::HeaderRep::add(const Name &name, const Value &value)
cf331c99
AR
47{
48 const http_hdr_type squidId = TranslateHeaderId(name); // HDR_OTHER OK
49 HttpHeaderEntry *e = new HttpHeaderEntry(squidId, name.image().c_str(),
26ac0430 50 value.toString().c_str());
cf331c99 51 theHeader.addEntry(e);
809fd5d3
AJ
52
53 if (squidId == HDR_CONTENT_LENGTH)
74174c03 54 theMessage.content_length = theHeader.getInt64(HDR_CONTENT_LENGTH);
cf331c99
AR
55}
56
57void
574b508c 58Adaptation::Ecap::HeaderRep::removeAny(const Name &name)
cf331c99
AR
59{
60 const http_hdr_type squidId = TranslateHeaderId(name);
61 if (squidId == HDR_OTHER)
62 theHeader.delByName(name.image().c_str());
63 else
64 theHeader.delById(squidId);
809fd5d3
AJ
65
66 if (squidId == HDR_CONTENT_LENGTH)
74174c03 67 theMessage.content_length = theHeader.getInt64(HDR_CONTENT_LENGTH);
cf331c99
AR
68}
69
12a410c3
AR
70void
71Adaptation::Ecap::HeaderRep::visitEach(libecap::NamedValueVisitor &visitor) const
72{
73 HttpHeaderPos pos = HttpHeaderInitPos;
74 while (HttpHeaderEntry *e = theHeader.getEntry(&pos)) {
75 const Name name(e->name.termedBuf()); // optimize: find std Names
76 name.assignHostId(e->id);
77 visitor.visit(name, Value(e->value.rawBuf(), e->value.size()));
78 }
79}
80
cf331c99 81libecap::Area
574b508c 82Adaptation::Ecap::HeaderRep::image() const
cf331c99
AR
83{
84 MemBuf mb;
85 mb.init();
86
87 Packer p;
88 packerToMemInit(&p, &mb);
89 theMessage.packInto(&p, true);
90 packerClean(&p);
91 return Area::FromTempBuffer(mb.content(), mb.contentSize());
92}
93
94// throws on failures
95void
574b508c 96Adaptation::Ecap::HeaderRep::parse(const Area &buf)
cf331c99
AR
97{
98 MemBuf mb;
99 mb.init();
100 mb.append(buf.start, buf.size);
101 http_status error;
102 Must(theMessage.parse(&mb, true, &error));
103}
104
77773405 105http_hdr_type
574b508c 106Adaptation::Ecap::HeaderRep::TranslateHeaderId(const Name &name)
77773405
AR
107{
108 if (name.assignedHostId())
109 return static_cast<http_hdr_type>(name.hostId());
110 return HDR_OTHER;
111}
112
113
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
AR
164 return protocolIcy;
165 case AnyP::PROTO_UNKNOWN:
166 return protocolUnknown; // until we remember the protocol image
39a19cb7 167 case AnyP::PROTO_NONE:
26ac0430
AJ
168 return Name();
169
39a19cb7 170 case AnyP::PROTO_MAX:
26ac0430 171 break; // should not happen
39a19cb7 172 // no default to catch AnyP::PROTO_ additions
cf331c99
AR
173 }
174 Must(false); // not reached
175 return Name();
176}
177
178void
574b508c 179Adaptation::Ecap::FirstLineRep::protocol(const Name &p)
cf331c99
AR
180{
181 // TODO: what happens if we fail to translate some protocol?
182 theMessage.protocol = TranslateProtocolId(p);
183}
184
555aedbf 185AnyP::ProtocolType
574b508c 186Adaptation::Ecap::FirstLineRep::TranslateProtocolId(const Name &name)
77773405
AR
187{
188 if (name.assignedHostId())
555aedbf
AR
189 return static_cast<AnyP::ProtocolType>(name.hostId());
190 return AnyP::PROTO_UNKNOWN;
77773405
AR
191}
192
cf331c99
AR
193
194/* RequestHeaderRep */
195
574b508c 196Adaptation::Ecap::RequestLineRep::RequestLineRep(HttpRequest &aMessage):
26ac0430 197 FirstLineRep(aMessage), theMessage(aMessage)
cf331c99
AR
198{
199}
200
201void
574b508c 202Adaptation::Ecap::RequestLineRep::uri(const Area &aUri)
cf331c99
AR
203{
204 // TODO: if method is not set, urlPath will assume it is not connect;
205 // Can we change urlParse API to remove the method parameter?
206 // TODO: optimize: urlPath should take constant URL buffer
207 char *buf = xstrdup(aUri.toString().c_str());
208 const bool ok = urlParse(theMessage.method, buf, &theMessage);
209 xfree(buf);
210 Must(ok);
211}
212
574b508c
AR
213Adaptation::Ecap::RequestLineRep::Area
214Adaptation::Ecap::RequestLineRep::uri() const
cf331c99 215{
dd31ab8f
AR
216 const char *fullUrl = urlCanonical(&theMessage);
217 Must(fullUrl);
218 // optimize: avoid copying by having an Area::Detail that locks theMessage
219 return Area::FromTempBuffer(fullUrl, strlen(fullUrl));
cf331c99
AR
220}
221
222void
574b508c 223Adaptation::Ecap::RequestLineRep::method(const Name &aMethod)
cf331c99
AR
224{
225 if (aMethod.assignedHostId()) {
226 const int id = aMethod.hostId();
227 Must(METHOD_NONE < id && id < METHOD_ENUM_END);
228 Must(id != METHOD_OTHER);
229 theMessage.method = HttpRequestMethod(static_cast<_method_t>(id));
230 } else {
231 const std::string &image = aMethod.image();
232 theMessage.method = HttpRequestMethod(image.data(),
26ac0430 233 image.data() + image.size());
cf331c99
AR
234 }
235}
236
574b508c
AR
237Adaptation::Ecap::RequestLineRep::Name
238Adaptation::Ecap::RequestLineRep::method() const
cf331c99
AR
239{
240 switch (theMessage.method.id()) {
26ac0430
AJ
241 case METHOD_GET:
242 return libecap::methodGet;
243 case METHOD_POST:
244 return libecap::methodPost;
245 case METHOD_PUT:
246 return libecap::methodPut;
247 case METHOD_HEAD:
248 return libecap::methodHead;
249 case METHOD_CONNECT:
250 return libecap::methodConnect;
251 case METHOD_DELETE:
252 return libecap::methodDelete;
253 case METHOD_TRACE:
254 return libecap::methodTrace;
255 default:
256 return Name(theMessage.method.image());
cf331c99
AR
257 }
258}
259
77773405 260libecap::Version
574b508c 261Adaptation::Ecap::RequestLineRep::version() const
77773405
AR
262{
263 return FirstLineRep::version();
264}
265
266void
574b508c 267Adaptation::Ecap::RequestLineRep::version(const libecap::Version &aVersion)
77773405
AR
268{
269 FirstLineRep::version(aVersion);
270}
271
272libecap::Name
574b508c 273Adaptation::Ecap::RequestLineRep::protocol() const
77773405
AR
274{
275 return FirstLineRep::protocol();
276}
277
278void
574b508c 279Adaptation::Ecap::RequestLineRep::protocol(const Name &p)
77773405
AR
280{
281 FirstLineRep::protocol(p);
282}
283
cf331c99
AR
284
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
AR
294{
295 // TODO: why is .status a enum? Do we not support unknown statuses?
296 theMessage.sline.status = static_cast<http_status>(code);
297}
298
299int
574b508c 300Adaptation::Ecap::StatusLineRep::statusCode() const
cf331c99
AR
301{
302 // TODO: see statusCode(code) TODO above
303 return static_cast<int>(theMessage.sline.status);
304}
305
306void
574b508c 307Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area &)
cf331c99
AR
308{
309 // Squid does not support custom reason phrases
310 theMessage.sline.reason = NULL;
311}
312
574b508c
AR
313Adaptation::Ecap::StatusLineRep::Area
314Adaptation::Ecap::StatusLineRep::reasonPhrase() const
cf331c99
AR
315{
316 return theMessage.sline.reason ?
26ac0430 317 Area::FromTempString(std::string(theMessage.sline.reason)) : Area();
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{
77773405 361 return !theBody ? BodySize() : BodySize(theBody->bodySize());
cf331c99
AR
362}
363
cf331c99
AR
364
365/* MessageRep */
366
574b508c 367Adaptation::Ecap::MessageRep::MessageRep(HttpMsg *rawHeader):
26ac0430
AJ
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}