MessageRep.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2020 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 
26 Adaptation::Ecap::HeaderRep::HeaderRep(Http::Message &aMessage): theHeader(aMessage.header),
27  theMessage(aMessage)
28 {
29 }
30 
31 bool
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 
40 Adaptation::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 
51 void
52 Adaptation::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 
63 void
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 
76 void
77 Adaptation::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 
87 libecap::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
97 void
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());
109  return Http::HdrType::OTHER;
110 }
111 
112 /* FirstLineRep */
113 
115 {
116 }
117 
118 libecap::Version
120 {
121  return libecap::Version(theMessage.http_ver.major,
122  theMessage.http_ver.minor);
123 }
124 
125 void
126 Adaptation::Ecap::FirstLineRep::version(const libecap::Version &aVersion)
127 {
128  theMessage.http_ver.major = aVersion.majr;
129  theMessage.http_ver.minor = aVersion.minr;
130 }
131 
132 libecap::Name
134 {
135  // TODO: optimize?
136  switch (theMessage.http_ver.protocol) {
137  case AnyP::PROTO_HTTP:
138  return libecap::protocolHttp;
139  case AnyP::PROTO_HTTPS:
140  return libecap::protocolHttps;
141  case AnyP::PROTO_FTP:
142  return libecap::protocolFtp;
143  case AnyP::PROTO_GOPHER:
144  return libecap::protocolGopher;
145  case AnyP::PROTO_WAIS:
146  return libecap::protocolWais;
147  case AnyP::PROTO_WHOIS:
148  return libecap::protocolWhois;
149  case AnyP::PROTO_URN:
150  return libecap::protocolUrn;
151  case AnyP::PROTO_ICP:
152  return protocolIcp;
153 #if USE_HTCP
154  case AnyP::PROTO_HTCP:
155  return protocolHtcp;
156 #endif
158  return protocolCacheObj;
159  case AnyP::PROTO_ICY:
160  return protocolIcy;
161  case AnyP::PROTO_COAP:
162  case AnyP::PROTO_COAPS: // use 'unknown' until libecap supports coap:// and coaps://
163  // other protocols defined in Squid but not libecap use 'unknown'
165  case AnyP::PROTO_SSL:
166  case AnyP::PROTO_TLS:
167  case AnyP::PROTO_UNKNOWN:
168  return protocolUnknown; // until we remember the protocol image
169  case AnyP::PROTO_NONE:
170  return Name();
171 
172  case AnyP::PROTO_MAX:
173  break; // should not happen
174  // no default to catch AnyP::PROTO_ additions
175  }
176  Must(false); // not reached
177  return Name();
178 }
179 
180 void
182 {
183  // TODO: what happens if we fail to translate some protocol?
184  theMessage.http_ver.protocol = TranslateProtocolId(p);
185 }
186 
189 {
190  if (name.assignedHostId())
191  return static_cast<AnyP::ProtocolType>(name.hostId());
192  return AnyP::PROTO_UNKNOWN;
193 }
194 
195 /* RequestHeaderRep */
196 
198  FirstLineRep(aMessage), theMessage(aMessage)
199 {
200 }
201 
202 void
204 {
205  // TODO: if method is not set, AnyP::Uri::parse will assume it is not connect;
206  // Can we change AnyP::Uri::parse API to remove the method parameter?
207  const auto ok = theMessage.url.parse(theMessage.method, SBuf(aUri.toString()));
208  Must(ok);
209 }
210 
213 {
214  const SBuf &fullUrl = theMessage.effectiveRequestUri();
215  // XXX: effectiveRequestUri() cannot return NULL or even empty string, some other problem?
216  Must(!fullUrl.isEmpty());
217  // optimize: avoid copying by having an Area::Detail that locks theMessage
218  return Area::FromTempBuffer(fullUrl.rawContent(), fullUrl.length());
219 }
220 
221 void
223 {
224  if (aMethod.assignedHostId()) {
225  const int id = aMethod.hostId();
227  Must(id != Http::METHOD_OTHER);
228  theMessage.method = HttpRequestMethod(static_cast<Http::MethodType>(id));
229  } else {
230  const std::string &image = aMethod.image();
231  theMessage.method.HttpRequestMethodXXX(image.c_str());
232  }
233 }
234 
237 {
238  switch (theMessage.method.id()) {
239  case Http::METHOD_GET:
240  return libecap::methodGet;
241  case Http::METHOD_POST:
242  return libecap::methodPost;
243  case Http::METHOD_PUT:
244  return libecap::methodPut;
245  case Http::METHOD_HEAD:
246  return libecap::methodHead;
248  return libecap::methodConnect;
249  case Http::METHOD_DELETE:
250  return libecap::methodDelete;
251  case Http::METHOD_TRACE:
252  return libecap::methodTrace;
253  default:
254  return Name(theMessage.method.image().toStdString());
255  }
256 }
257 
258 libecap::Version
260 {
261  return FirstLineRep::version();
262 }
263 
264 void
265 Adaptation::Ecap::RequestLineRep::version(const libecap::Version &aVersion)
266 {
267  FirstLineRep::version(aVersion);
268 }
269 
270 libecap::Name
272 {
273  return FirstLineRep::protocol();
274 }
275 
276 void
278 {
280 }
281 
282 /* ReplyHeaderRep */
283 
285  FirstLineRep(aMessage), theMessage(aMessage)
286 {
287 }
288 
289 void
291 {
292  theMessage.sline.set(theMessage.sline.version, static_cast<Http::StatusCode>(code), nullptr);
293 }
294 
295 int
297 {
298  // TODO: remove cast when possible
299  return static_cast<int>(theMessage.sline.status());
300 }
301 
302 void
304 {
305  // Squid does not support external custom reason phrases so we have
306  // to just reset it (in case there was a custom internal reason set)
307  theMessage.sline.resetReason();
308 }
309 
312 {
313  return Area::FromTempString(std::string(theMessage.sline.reason()));
314 }
315 
316 libecap::Version
318 {
319  return FirstLineRep::version();
320 }
321 
322 void
323 Adaptation::Ecap::StatusLineRep::version(const libecap::Version &aVersion)
324 {
325  FirstLineRep::version(aVersion);
326 }
327 
328 libecap::Name
330 {
331  return FirstLineRep::protocol();
332 }
333 
334 void
336 {
338 }
339 
340 /* BodyRep */
341 
343 {
344 }
345 
346 void
348 {
349  Must(!theBody);
350  Must(aBody != NULL);
351  theBody = aBody;
352 }
353 
356 {
357  return (theBody != nullptr && theBody->bodySizeKnown()) ? BodySize(theBody->bodySize()) : BodySize();
358 }
359 
360 /* MessageRep */
361 
363  theMessage(rawHeader), theFirstLineRep(NULL),
364  theHeaderRep(NULL), theBodyRep(NULL)
365 {
366  Must(theMessage.header); // we do not want to represent a missing message
367 
368  if (HttpRequest *req = dynamic_cast<HttpRequest*>(theMessage.header))
369  theFirstLineRep = new RequestLineRep(*req);
370  else if (HttpReply *rep = dynamic_cast<HttpReply*>(theMessage.header))
371  theFirstLineRep = new StatusLineRep(*rep);
372  else
373  Must(false); // unknown message header type
374 
376 
377  if (theMessage.body_pipe != NULL)
379 }
380 
382 {
383  delete theBodyRep;
384  delete theHeaderRep;
385  delete theFirstLineRep;
386 }
387 
388 libecap::shared_ptr<libecap::Message>
390 {
391  Http::Message *hdr = theMessage.header->clone();
392  hdr->body_pipe = NULL; // if any; TODO: remove pipe cloning from ::clone?
393  libecap::shared_ptr<libecap::Message> res(new MessageRep(hdr));
394 
395  // restore indication of a body if needed, but not the pipe
396  if (theMessage.header->body_pipe != NULL)
397  res->addBody();
398 
399  return res;
400 }
401 
402 libecap::FirstLine &
404 {
405  return *theFirstLineRep;
406 }
407 
408 const libecap::FirstLine &
410 {
411  return *theFirstLineRep;
412 }
413 
414 libecap::Header &
416 {
417  return *theHeaderRep;
418 }
419 
420 const libecap::Header &
422 {
423  return *theHeaderRep;
424 }
425 
426 libecap::Body *
428 {
429  return theBodyRep;
430 }
431 
432 void
434 {
435  Must(!theBodyRep);
436  Must(!theMessage.body_pipe); // set in tieBody()
437  theBodyRep = new BodyRep(NULL);
438 }
439 
440 void
442 {
443  Must(theBodyRep != NULL); // addBody must be called first
444  Must(!theMessage.header->body_pipe);
445  Must(!theMessage.body_pipe);
446  theMessage.header->body_pipe = new BodyPipe(x);
447  theMessage.body_pipe = theMessage.header->body_pipe;
448  theBodyRep->tie(theMessage.body_pipe);
449 }
450 
451 const libecap::Body *Adaptation::Ecap::MessageRep::body() const
452 {
453  return theBodyRep;
454 }
455 
@ METHOD_OTHER
Definition: MethodType.h:95
void tie(const BodyPipe::Pointer &aBody)
Definition: MessageRep.cc:347
const libecap::Name protocolIcp
virtual Area uri() const
Definition: MessageRep.cc:212
@ METHOD_HEAD
Definition: MethodType.h:28
common parts of HttpRequest and HttpReply
Definition: Message.h:25
virtual int statusCode() const
Definition: MessageRep.cc:296
@ PROTO_COAPS
Definition: ProtocolType.h:29
BodyPipe::Pointer body_pipe
optional pipeline to receive message body
Definition: Message.h:98
static Http::HdrType TranslateHeaderId(const Name &name)
Definition: MessageRep.cc:105
@ PROTO_SSL
Definition: ProtocolType.h:41
virtual Area reasonPhrase() const
Definition: MessageRep.cc:311
@ METHOD_ENUM_END
Definition: MethodType.h:96
HttpHeader header
Definition: Message.h:75
bool isEmpty() const
Definition: SBuf.h:420
ssize_t HttpHeaderPos
Definition: HttpHeader.h:45
@ PROTO_NONE
Definition: ProtocolType.h:24
virtual libecap::shared_ptr< libecap::Message > clone() const
Definition: MessageRep.cc:389
#define HttpHeaderInitPos
Definition: HttpHeader.h:48
void error(char *format,...)
void init(mb_size_t szInit, mb_size_t szMax)
Definition: MemBuf.cc:96
Definition: SBuf.h:86
libecap::FirstLine * theFirstLineRep
Definition: MessageRep.h:170
StatusCode
Definition: StatusCode.h:20
@ PROTO_COAP
Definition: ProtocolType.h:28
const libecap::Name protocolIcy
@ PROTO_UNKNOWN
Definition: ProtocolType.h:43
@ CONTENT_LENGTH
virtual void visitEach(libecap::NamedValueVisitor &visitor) const
Definition: MessageRep.cc:77
HeaderRep(Http::Message &aMessage)
Definition: MessageRep.cc:26
@ PROTO_URN
Definition: ProtocolType.h:37
StatusLineRep(HttpReply &aMessage)
Definition: MessageRep.cc:284
ProtocolType
Definition: ProtocolType.h:23
virtual void parse(const Area &buf)
Definition: MessageRep.cc:98
libecap::Version version() const
Definition: MessageRep.cc:119
mb_size_t contentSize() const
available data size
Definition: MemBuf.h:47
#define NULL
Definition: types.h:166
const char * rawContent() const
Definition: SBuf.cc:519
virtual Value value(const Name &name) const
Definition: MessageRep.cc:41
@ PROTO_MAX
Definition: ProtocolType.h:44
@ PROTO_TLS
Definition: ProtocolType.h:40
@ METHOD_DELETE
Definition: MethodType.h:32
Definition: MemBuf.h:23
unsigned char code
Definition: html_quote.c:20
@ METHOD_CONNECT
Definition: MethodType.h:29
BodyRep(const BodyPipe::Pointer &aBody)
Definition: MessageRep.cc:342
virtual libecap::Header & header()
Definition: MessageRep.cc:415
virtual void add(const Name &name, const Value &value)
Definition: MessageRep.cc:52
virtual BodySize bodySize() const
Definition: MessageRep.cc:355
@ METHOD_POST
Definition: MethodType.h:26
Adaptation::Message theMessage
Definition: MessageRep.h:169
@ METHOD_PUT
Definition: MethodType.h:27
virtual libecap::Body * body()
Definition: MessageRep.cc:427
@ METHOD_TRACE
Definition: MethodType.h:30
@ PROTO_GOPHER
Definition: ProtocolType.h:30
const char * c_str()
Definition: SBuf.cc:526
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:404
virtual void removeAny(const Name &name)
Definition: MessageRep.cc:64
void tieBody(Ecap::XactionRep *x)
Definition: MessageRep.cc:441
enum Http::_method_t MethodType
virtual libecap::Version version() const
Definition: MessageRep.cc:317
@ PROTO_CACHE_OBJECT
Definition: ProtocolType.h:32
@ PROTO_AUTHORITY_FORM
Definition: ProtocolType.h:42
@ PROTO_WHOIS
Definition: ProtocolType.h:38
@ 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:91
virtual Area image() const
Definition: MessageRep.cc:88
const libecap::Name protocolCacheObj
@ PROTO_WAIS
Definition: ProtocolType.h:31
char * content()
start of the added data
Definition: MemBuf.h:41
size_type size() const
Definition: SquidString.h:72
@ METHOD_NONE
Definition: MethodType.h:22
BodyPipePointer body_pipe
Definition: Message.h:46
virtual Name method() const
Definition: MessageRep.cc:236
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
virtual libecap::FirstLine & firstLine()
Definition: MessageRep.cc:403
const libecap::Name protocolHtcp
virtual Name protocol() const
Definition: MessageRep.cc:271
libecap::BodySize BodySize
Definition: MessageRep.h:132
@ PROTO_HTCP
Definition: ProtocolType.h:35
static AnyP::ProtocolType TranslateProtocolId(const Name &name)
Definition: MessageRep.cc:188
virtual bool hasAny(const Name &name) const
Definition: MessageRep.cc:32
virtual libecap::Version version() const
Definition: MessageRep.cc:259
@ PROTO_ICY
Definition: ProtocolType.h:39
@ METHOD_GET
Definition: MethodType.h:25
FirstLineRep(Http::Message &aMessage)
Definition: MessageRep.cc:114
const libecap::Name protocolUnknown
MessageRep(Http::Message *rawHeader)
Definition: MessageRep.cc:362
void const char * buf
Definition: stub_helper.cc:16
virtual Name protocol() const
Definition: MessageRep.cc:329
@ PROTO_ICP
Definition: ProtocolType.h:33
Header * header
Definition: Message.h:42
RequestLineRep(HttpRequest &aMessage)
Definition: MessageRep.cc:197

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors