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
155 case AnyP::PROTO_ICY:
156 return protocolIcy;
157 case AnyP::PROTO_COAP:
158 case AnyP::PROTO_COAPS: // use 'unknown' until libecap supports coap:// and coaps://
159 // other protocols defined in Squid but not libecap use 'unknown'
161 case AnyP::PROTO_SSL:
162 case AnyP::PROTO_TLS:
164 return protocolUnknown; // until we remember the protocol image
165 case AnyP::PROTO_NONE:
166 return Name();
167
168 case AnyP::PROTO_MAX:
169 break; // should not happen
170 // no default to catch AnyP::PROTO_ additions
171 }
172 Must(false); // not reached
173 return Name();
174}
175
176void
178{
179 // TODO: what happens if we fail to translate some protocol?
180 theMessage.http_ver.protocol = TranslateProtocolId(p);
181}
182
185{
186 if (name.assignedHostId())
187 return static_cast<AnyP::ProtocolType>(name.hostId());
188 return AnyP::PROTO_UNKNOWN;
189}
190
191/* RequestHeaderRep */
192
194 FirstLineRep(aMessage), theMessage(aMessage)
195{
196}
197
198void
200{
201 // TODO: if method is not set, AnyP::Uri::parse will assume it is not connect;
202 // Can we change AnyP::Uri::parse API to remove the method parameter?
203 const auto ok = theMessage.url.parse(theMessage.method, SBuf(aUri.toString()));
204 Must(ok);
205}
206
209{
210 const SBuf &fullUrl = theMessage.effectiveRequestUri();
211 // XXX: effectiveRequestUri() cannot return NULL or even empty string, some other problem?
212 Must(!fullUrl.isEmpty());
213 // optimize: avoid copying by having an Area::Detail that locks theMessage
214 return Area::FromTempBuffer(fullUrl.rawContent(), fullUrl.length());
215}
216
217void
219{
220 if (aMethod.assignedHostId()) {
221 const int id = aMethod.hostId();
224 theMessage.method = HttpRequestMethod(static_cast<Http::MethodType>(id));
225 } else {
226 const std::string &image = aMethod.image();
227 theMessage.method.HttpRequestMethodXXX(image.c_str());
228 }
229}
230
233{
234 switch (theMessage.method.id()) {
235 case Http::METHOD_GET:
236 return libecap::methodGet;
238 return libecap::methodPost;
239 case Http::METHOD_PUT:
240 return libecap::methodPut;
242 return libecap::methodHead;
244 return libecap::methodConnect;
246 return libecap::methodDelete;
248 return libecap::methodTrace;
249 default:
250 return Name(theMessage.method.image().toStdString());
251 }
252}
253
254libecap::Version
256{
257 return FirstLineRep::version();
258}
259
260void
261Adaptation::Ecap::RequestLineRep::version(const libecap::Version &aVersion)
262{
263 FirstLineRep::version(aVersion);
264}
265
266libecap::Name
268{
269 return FirstLineRep::protocol();
270}
271
272void
274{
276}
277
278/* ReplyHeaderRep */
279
281 FirstLineRep(aMessage), theMessage(aMessage)
282{
283}
284
285void
287{
288 theMessage.sline.set(theMessage.sline.version, static_cast<Http::StatusCode>(code), nullptr);
289}
290
291int
293{
294 // TODO: remove cast when possible
295 return static_cast<int>(theMessage.sline.status());
296}
297
298void
300{
301 // Squid does not support external custom reason phrases so we have
302 // to just reset it (in case there was a custom internal reason set)
303 theMessage.sline.resetReason();
304}
305
308{
309 return Area::FromTempString(std::string(theMessage.sline.reason()));
310}
311
312libecap::Version
314{
315 return FirstLineRep::version();
316}
317
318void
319Adaptation::Ecap::StatusLineRep::version(const libecap::Version &aVersion)
320{
321 FirstLineRep::version(aVersion);
322}
323
324libecap::Name
326{
327 return FirstLineRep::protocol();
328}
329
330void
332{
334}
335
336/* BodyRep */
337
339{
340}
341
342void
344{
345 Must(!theBody);
346 Must(aBody != nullptr);
347 theBody = aBody;
348}
349
352{
353 return (theBody != nullptr && theBody->bodySizeKnown()) ? BodySize(theBody->bodySize()) : BodySize();
354}
355
356/* MessageRep */
357
359 theMessage(rawHeader), theFirstLineRep(nullptr),
360 theHeaderRep(nullptr), theBodyRep(nullptr)
361{
362 Must(theMessage.header); // we do not want to represent a missing message
363
364 if (HttpRequest *req = dynamic_cast<HttpRequest*>(theMessage.header))
366 else if (HttpReply *rep = dynamic_cast<HttpReply*>(theMessage.header))
367 theFirstLineRep = new StatusLineRep(*rep);
368 else
369 Must(false); // unknown message header type
370
372
373 if (theMessage.body_pipe != nullptr)
375}
376
378{
379 delete theBodyRep;
380 delete theHeaderRep;
381 delete theFirstLineRep;
382}
383
384libecap::shared_ptr<libecap::Message>
386{
387 Http::Message *hdr = theMessage.header->clone();
388 hdr->body_pipe = nullptr; // if any; TODO: remove pipe cloning from ::clone?
389 libecap::shared_ptr<libecap::Message> res(new MessageRep(hdr));
390
391 // restore indication of a body if needed, but not the pipe
392 if (theMessage.header->body_pipe != nullptr)
393 res->addBody();
394
395 return res;
396}
397
398libecap::FirstLine &
400{
401 return *theFirstLineRep;
402}
403
404const libecap::FirstLine &
406{
407 return *theFirstLineRep;
408}
409
410libecap::Header &
412{
413 return *theHeaderRep;
414}
415
416const libecap::Header &
418{
419 return *theHeaderRep;
420}
421
422libecap::Body *
424{
425 return theBodyRep;
426}
427
428void
430{
431 Must(!theBodyRep);
432 Must(!theMessage.body_pipe); // set in tieBody()
433 theBodyRep = new BodyRep(nullptr);
434}
435
436void
438{
439 Must(theBodyRep != nullptr); // addBody must be called first
440 Must(!theMessage.header->body_pipe);
441 Must(!theMessage.body_pipe);
442 theMessage.header->body_pipe = new BodyPipe(x);
443 theMessage.body_pipe = theMessage.header->body_pipe;
444 theBodyRep->tie(theMessage.body_pipe);
445}
446
447const libecap::Body *Adaptation::Ecap::MessageRep::body() const
448{
449 return theBodyRep;
450}
451
ssize_t HttpHeaderPos
Definition: HttpHeader.h:45
#define HttpHeaderInitPos
Definition: HttpHeader.h:48
#define Must(condition)
Definition: TextException.h:75
void error(char *format,...)
BodyRep(const BodyPipe::Pointer &aBody)
Definition: MessageRep.cc:338
BodySize bodySize() const override
Definition: MessageRep.cc:351
libecap::BodySize BodySize
Definition: MessageRep.h:132
void tie(const BodyPipe::Pointer &aBody)
Definition: MessageRep.cc:343
libecap::Version version() const
Definition: MessageRep.cc:119
static AnyP::ProtocolType TranslateProtocolId(const Name &name)
Definition: MessageRep.cc:184
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:358
libecap::FirstLine * theFirstLineRep
Definition: MessageRep.h:170
libecap::Body * body() override
Definition: MessageRep.cc:423
libecap::FirstLine & firstLine() override
Definition: MessageRep.cc:399
libecap::Header & header() override
Definition: MessageRep.cc:411
libecap::shared_ptr< libecap::Message > clone() const override
Definition: MessageRep.cc:385
void tieBody(Ecap::XactionRep *x)
Definition: MessageRep.cc:437
libecap::Version version() const override
Definition: MessageRep.cc:255
Name method() const override
Definition: MessageRep.cc:232
Area uri() const override
Definition: MessageRep.cc:208
RequestLineRep(HttpRequest &aMessage)
Definition: MessageRep.cc:193
Name protocol() const override
Definition: MessageRep.cc:267
int statusCode() const override
Definition: MessageRep.cc:292
libecap::Version version() const override
Definition: MessageRep.cc:313
Name protocol() const override
Definition: MessageRep.cc:325
Area reasonPhrase() const override
Definition: MessageRep.cc:307
StatusLineRep(HttpReply &aMessage)
Definition: MessageRep.cc:280
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
const libecap::Name protocolIcp
const libecap::Name protocolUnknown
const libecap::Name protocolHtcp
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:41
@ PROTO_HTCP
Definition: ProtocolType.h:33
@ PROTO_TLS
Definition: ProtocolType.h:38
@ PROTO_AUTHORITY_FORM
Definition: ProtocolType.h:40
@ PROTO_ICY
Definition: ProtocolType.h:37
@ PROTO_HTTP
Definition: ProtocolType.h:25
@ PROTO_COAP
Definition: ProtocolType.h:28
@ PROTO_FTP
Definition: ProtocolType.h:26
@ PROTO_WHOIS
Definition: ProtocolType.h:36
@ PROTO_MAX
Definition: ProtocolType.h:42
@ PROTO_SSL
Definition: ProtocolType.h:39
@ PROTO_COAPS
Definition: ProtocolType.h:29
@ PROTO_ICP
Definition: ProtocolType.h:31
@ PROTO_URN
Definition: ProtocolType.h:35
@ 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
int code
Definition: smb-errors.c:145

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors