]> 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
AR
1/*
2 * DEBUG: section XXX
3 */
4
5#include "squid.h"
cf331c99
AR
6#include "HttpRequest.h"
7#include "HttpReply.h"
8#include "BodyPipe.h"
9#include "TextException.h"
cf331c99
AR
10#include <libecap/common/names.h>
11#include <libecap/common/area.h>
12#include <libecap/common/version.h>
1f3c65fc
AR
13#include "adaptation/ecap/MessageRep.h"
14#include "adaptation/ecap/XactionRep.h"
15#include "adaptation/ecap/Host.h" /* for protocol constants */
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);
c1945e7d 41 return Value::FromTempString(value.termedBuf());
cf331c99
AR
42}
43
44void
574b508c 45Adaptation::Ecap::HeaderRep::add(const Name &name, const Value &value)
cf331c99
AR
46{
47 const http_hdr_type squidId = TranslateHeaderId(name); // HDR_OTHER OK
48 HttpHeaderEntry *e = new HttpHeaderEntry(squidId, name.image().c_str(),
26ac0430 49 value.toString().c_str());
cf331c99
AR
50 theHeader.addEntry(e);
51}
52
53void
574b508c 54Adaptation::Ecap::HeaderRep::removeAny(const Name &name)
cf331c99
AR
55{
56 const http_hdr_type squidId = TranslateHeaderId(name);
57 if (squidId == HDR_OTHER)
58 theHeader.delByName(name.image().c_str());
59 else
60 theHeader.delById(squidId);
61}
62
63libecap::Area
574b508c 64Adaptation::Ecap::HeaderRep::image() const
cf331c99
AR
65{
66 MemBuf mb;
67 mb.init();
68
69 Packer p;
70 packerToMemInit(&p, &mb);
71 theMessage.packInto(&p, true);
72 packerClean(&p);
73 return Area::FromTempBuffer(mb.content(), mb.contentSize());
74}
75
76// throws on failures
77void
574b508c 78Adaptation::Ecap::HeaderRep::parse(const Area &buf)
cf331c99
AR
79{
80 MemBuf mb;
81 mb.init();
82 mb.append(buf.start, buf.size);
83 http_status error;
84 Must(theMessage.parse(&mb, true, &error));
85}
86
77773405 87http_hdr_type
574b508c 88Adaptation::Ecap::HeaderRep::TranslateHeaderId(const Name &name)
77773405
AR
89{
90 if (name.assignedHostId())
91 return static_cast<http_hdr_type>(name.hostId());
92 return HDR_OTHER;
93}
94
95
96/* FirstLineRep */
97
574b508c 98Adaptation::Ecap::FirstLineRep::FirstLineRep(HttpMsg &aMessage): theMessage(aMessage)
77773405
AR
99{
100}
101
cf331c99 102libecap::Version
574b508c 103Adaptation::Ecap::FirstLineRep::version() const
cf331c99
AR
104{
105 return libecap::Version(theMessage.http_ver.major,
26ac0430 106 theMessage.http_ver.minor);
cf331c99
AR
107}
108
109void
574b508c 110Adaptation::Ecap::FirstLineRep::version(const libecap::Version &aVersion)
cf331c99
AR
111{
112 theMessage.http_ver.major = aVersion.majr;
113 theMessage.http_ver.minor = aVersion.minr;
114}
115
116libecap::Name
574b508c 117Adaptation::Ecap::FirstLineRep::protocol() const
cf331c99
AR
118{
119 // TODO: optimize?
120 switch (theMessage.protocol) {
26ac0430
AJ
121 case PROTO_HTTP:
122 return libecap::protocolHttp;
123 case PROTO_HTTPS:
124 return libecap::protocolHttps;
125 case PROTO_FTP:
126 return libecap::protocolFtp;
127 case PROTO_GOPHER:
128 return libecap::protocolGopher;
129 case PROTO_WAIS:
130 return libecap::protocolWais;
131 case PROTO_WHOIS:
132 return libecap::protocolWhois;
133 case PROTO_URN:
134 return libecap::protocolUrn;
135 case PROTO_ICP:
136 return protocolIcp;
cf331c99 137#if USE_HTCP
26ac0430
AJ
138 case PROTO_HTCP:
139 return protocolHtcp;
cf331c99 140#endif
26ac0430
AJ
141 case PROTO_CACHEOBJ:
142 return protocolCacheObj;
143 case PROTO_INTERNAL:
144 return protocolInternal;
145 case PROTO_NONE:
146 return Name();
147
148 case PROTO_MAX:
149 break; // should not happen
cf331c99
AR
150 // no default to catch PROTO_ additions
151 }
152 Must(false); // not reached
153 return Name();
154}
155
156void
574b508c 157Adaptation::Ecap::FirstLineRep::protocol(const Name &p)
cf331c99
AR
158{
159 // TODO: what happens if we fail to translate some protocol?
160 theMessage.protocol = TranslateProtocolId(p);
161}
162
77773405 163protocol_t
574b508c 164Adaptation::Ecap::FirstLineRep::TranslateProtocolId(const Name &name)
77773405
AR
165{
166 if (name.assignedHostId())
167 return static_cast<protocol_t>(name.hostId());
168 return PROTO_NONE; // no PROTO_OTHER
169}
170
cf331c99
AR
171
172/* RequestHeaderRep */
173
574b508c 174Adaptation::Ecap::RequestLineRep::RequestLineRep(HttpRequest &aMessage):
26ac0430 175 FirstLineRep(aMessage), theMessage(aMessage)
cf331c99
AR
176{
177}
178
179void
574b508c 180Adaptation::Ecap::RequestLineRep::uri(const Area &aUri)
cf331c99
AR
181{
182 // TODO: if method is not set, urlPath will assume it is not connect;
183 // Can we change urlParse API to remove the method parameter?
184 // TODO: optimize: urlPath should take constant URL buffer
185 char *buf = xstrdup(aUri.toString().c_str());
186 const bool ok = urlParse(theMessage.method, buf, &theMessage);
187 xfree(buf);
188 Must(ok);
189}
190
574b508c
AR
191Adaptation::Ecap::RequestLineRep::Area
192Adaptation::Ecap::RequestLineRep::uri() const
cf331c99 193{
bb790702 194 return Area::FromTempBuffer(theMessage.urlpath.rawBuf(),
26ac0430 195 theMessage.urlpath.size());
cf331c99
AR
196}
197
198void
574b508c 199Adaptation::Ecap::RequestLineRep::method(const Name &aMethod)
cf331c99
AR
200{
201 if (aMethod.assignedHostId()) {
202 const int id = aMethod.hostId();
203 Must(METHOD_NONE < id && id < METHOD_ENUM_END);
204 Must(id != METHOD_OTHER);
205 theMessage.method = HttpRequestMethod(static_cast<_method_t>(id));
206 } else {
207 const std::string &image = aMethod.image();
208 theMessage.method = HttpRequestMethod(image.data(),
26ac0430 209 image.data() + image.size());
cf331c99
AR
210 }
211}
212
574b508c
AR
213Adaptation::Ecap::RequestLineRep::Name
214Adaptation::Ecap::RequestLineRep::method() const
cf331c99
AR
215{
216 switch (theMessage.method.id()) {
26ac0430
AJ
217 case METHOD_GET:
218 return libecap::methodGet;
219 case METHOD_POST:
220 return libecap::methodPost;
221 case METHOD_PUT:
222 return libecap::methodPut;
223 case METHOD_HEAD:
224 return libecap::methodHead;
225 case METHOD_CONNECT:
226 return libecap::methodConnect;
227 case METHOD_DELETE:
228 return libecap::methodDelete;
229 case METHOD_TRACE:
230 return libecap::methodTrace;
231 default:
232 return Name(theMessage.method.image());
cf331c99
AR
233 }
234}
235
77773405 236libecap::Version
574b508c 237Adaptation::Ecap::RequestLineRep::version() const
77773405
AR
238{
239 return FirstLineRep::version();
240}
241
242void
574b508c 243Adaptation::Ecap::RequestLineRep::version(const libecap::Version &aVersion)
77773405
AR
244{
245 FirstLineRep::version(aVersion);
246}
247
248libecap::Name
574b508c 249Adaptation::Ecap::RequestLineRep::protocol() const
77773405
AR
250{
251 return FirstLineRep::protocol();
252}
253
254void
574b508c 255Adaptation::Ecap::RequestLineRep::protocol(const Name &p)
77773405
AR
256{
257 FirstLineRep::protocol(p);
258}
259
cf331c99
AR
260
261/* ReplyHeaderRep */
262
574b508c 263Adaptation::Ecap::StatusLineRep::StatusLineRep(HttpReply &aMessage):
26ac0430 264 FirstLineRep(aMessage), theMessage(aMessage)
cf331c99
AR
265{
266}
267
268void
574b508c 269Adaptation::Ecap::StatusLineRep::statusCode(int code)
cf331c99
AR
270{
271 // TODO: why is .status a enum? Do we not support unknown statuses?
272 theMessage.sline.status = static_cast<http_status>(code);
273}
274
275int
574b508c 276Adaptation::Ecap::StatusLineRep::statusCode() const
cf331c99
AR
277{
278 // TODO: see statusCode(code) TODO above
279 return static_cast<int>(theMessage.sline.status);
280}
281
282void
574b508c 283Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area &)
cf331c99
AR
284{
285 // Squid does not support custom reason phrases
286 theMessage.sline.reason = NULL;
287}
288
574b508c
AR
289Adaptation::Ecap::StatusLineRep::Area
290Adaptation::Ecap::StatusLineRep::reasonPhrase() const
cf331c99
AR
291{
292 return theMessage.sline.reason ?
26ac0430 293 Area::FromTempString(std::string(theMessage.sline.reason)) : Area();
cf331c99
AR
294}
295
77773405 296libecap::Version
574b508c 297Adaptation::Ecap::StatusLineRep::version() const
77773405
AR
298{
299 return FirstLineRep::version();
300}
301
302void
574b508c 303Adaptation::Ecap::StatusLineRep::version(const libecap::Version &aVersion)
77773405
AR
304{
305 FirstLineRep::version(aVersion);
306}
307
308libecap::Name
574b508c 309Adaptation::Ecap::StatusLineRep::protocol() const
77773405
AR
310{
311 return FirstLineRep::protocol();
312}
313
314void
574b508c 315Adaptation::Ecap::StatusLineRep::protocol(const Name &p)
77773405
AR
316{
317 FirstLineRep::protocol(p);
318}
cf331c99
AR
319
320/* BodyRep */
321
574b508c 322Adaptation::Ecap::BodyRep::BodyRep(const BodyPipe::Pointer &aBody): theBody(aBody)
cf331c99
AR
323{
324}
325
77773405 326void
574b508c 327Adaptation::Ecap::BodyRep::tie(const BodyPipe::Pointer &aBody)
77773405
AR
328{
329 Must(!theBody);
330 Must(aBody != NULL);
331 theBody = aBody;
332}
333
574b508c
AR
334Adaptation::Ecap::BodyRep::BodySize
335Adaptation::Ecap::BodyRep::bodySize() const
cf331c99 336{
77773405 337 return !theBody ? BodySize() : BodySize(theBody->bodySize());
cf331c99
AR
338}
339
cf331c99
AR
340
341/* MessageRep */
342
574b508c 343Adaptation::Ecap::MessageRep::MessageRep(HttpMsg *rawHeader):
26ac0430
AJ
344 theMessage(rawHeader), theFirstLineRep(NULL),
345 theHeaderRep(NULL), theBodyRep(NULL)
cf331c99
AR
346{
347 Must(theMessage.header); // we do not want to represent a missing message
348
349 if (HttpRequest *req = dynamic_cast<HttpRequest*>(theMessage.header))
77773405 350 theFirstLineRep = new RequestLineRep(*req);
e1381638
AJ
351 else if (HttpReply *rep = dynamic_cast<HttpReply*>(theMessage.header))
352 theFirstLineRep = new StatusLineRep(*rep);
cf331c99 353 else
e1381638 354 Must(false); // unknown message header type
cf331c99 355
77773405
AR
356 theHeaderRep = new HeaderRep(*theMessage.header);
357
cf331c99
AR
358 if (theMessage.body_pipe != NULL)
359 theBodyRep = new BodyRep(theMessage.body_pipe);
360}
361
574b508c 362Adaptation::Ecap::MessageRep::~MessageRep()
cf331c99 363{
77773405 364 delete theBodyRep;
80031342
AR
365 delete theHeaderRep;
366 delete theFirstLineRep;
77773405
AR
367}
368
369libecap::shared_ptr<libecap::Message>
574b508c 370Adaptation::Ecap::MessageRep::clone() const
77773405
AR
371{
372 HttpMsg *hdr = theMessage.header->clone();
373 hdr->body_pipe = NULL; // if any; TODO: remove pipe cloning from ::clone?
374 libecap::shared_ptr<libecap::Message> res(new MessageRep(hdr));
375
376 // restore indication of a body if needed, but not the pipe
377 if (theMessage.header->body_pipe != NULL)
378 res->addBody();
379
380 return res;
381}
382
383libecap::FirstLine &
574b508c 384Adaptation::Ecap::MessageRep::firstLine()
77773405
AR
385{
386 return *theFirstLineRep;
387}
388
389const libecap::FirstLine &
574b508c 390Adaptation::Ecap::MessageRep::firstLine() const
77773405
AR
391{
392 return *theFirstLineRep;
cf331c99
AR
393}
394
395libecap::Header &
574b508c 396Adaptation::Ecap::MessageRep::header()
cf331c99
AR
397{
398 return *theHeaderRep;
399}
400
401const libecap::Header &
574b508c 402Adaptation::Ecap::MessageRep::header() const
cf331c99
AR
403{
404 return *theHeaderRep;
405}
406
407libecap::Body *
574b508c 408Adaptation::Ecap::MessageRep::body()
cf331c99
AR
409{
410 return theBodyRep;
411}
412
413void
574b508c 414Adaptation::Ecap::MessageRep::addBody()
cf331c99 415{
cf331c99 416 Must(!theBodyRep);
77773405
AR
417 Must(!theMessage.body_pipe); // set in tieBody()
418 theBodyRep = new BodyRep(NULL);
419}
420
421void
574b508c 422Adaptation::Ecap::MessageRep::tieBody(Adaptation::Ecap::XactionRep *x)
77773405
AR
423{
424 Must(theBodyRep != NULL); // addBody must be called first
ce367911 425 Must(!theMessage.header->body_pipe);
cf331c99 426 Must(!theMessage.body_pipe);
ce367911
AR
427 theMessage.header->body_pipe = new BodyPipe(x);
428 theMessage.body_pipe = theMessage.header->body_pipe;
77773405 429 theBodyRep->tie(theMessage.body_pipe);
cf331c99
AR
430}
431
574b508c 432const libecap::Body *Adaptation::Ecap::MessageRep::body() const
cf331c99
AR
433{
434 return theBodyRep;
435}