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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors