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

 

Introduction

Documentation

Support

Miscellaneous