MessageRep.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 #include "URL.h"
24 
25 /* HeaderRep */
26 
27 Adaptation::Ecap::HeaderRep::HeaderRep(Http::Message &aMessage): theHeader(aMessage.header),
28  theMessage(aMessage)
29 {
30 }
31 
32 bool
34 {
35  const Http::HdrType squidId = TranslateHeaderId(name);
36  return squidId == Http::HdrType::OTHER ?
37  theHeader.hasNamed(name.image().c_str(), name.image().size()) :
38  static_cast<bool>(theHeader.has(squidId));
39 }
40 
41 Adaptation::Ecap::HeaderRep::Value
43 {
44  const Http::HdrType squidId = TranslateHeaderId(name);
45  const String value = squidId == Http::HdrType::OTHER ?
46  theHeader.getByName(name.image().c_str()) :
47  theHeader.getStrOrList(squidId);
48  return value.size() > 0 ?
49  Value::FromTempString(value.termedBuf()) : Value();
50 }
51 
52 void
53 Adaptation::Ecap::HeaderRep::add(const Name &name, const Value &value)
54 {
55  const Http::HdrType squidId = TranslateHeaderId(name); // Http::HdrType::OTHER OK
56  HttpHeaderEntry *e = new HttpHeaderEntry(squidId, SBuf(name.image()),
57  value.toString().c_str());
58  theHeader.addEntry(e);
59 
60  if (squidId == Http::HdrType::CONTENT_LENGTH)
61  theMessage.content_length = theHeader.getInt64(Http::HdrType::CONTENT_LENGTH);
62 }
63 
64 void
66 {
67  const Http::HdrType squidId = TranslateHeaderId(name);
68  if (squidId == Http::HdrType::OTHER)
69  theHeader.delByName(name.image().c_str());
70  else
71  theHeader.delById(squidId);
72 
73  if (squidId == Http::HdrType::CONTENT_LENGTH)
74  theMessage.content_length = theHeader.getInt64(Http::HdrType::CONTENT_LENGTH);
75 }
76 
77 void
78 Adaptation::Ecap::HeaderRep::visitEach(libecap::NamedValueVisitor &visitor) const
79 {
81  while (HttpHeaderEntry *e = theHeader.getEntry(&pos)) {
82  const Name name(std::string(e->name.rawContent(), e->name.length())); // optimize: find std Names
83  name.assignHostId(e->id);
84  visitor.visit(name, Value(e->value.rawBuf(), e->value.size()));
85  }
86 }
87 
88 libecap::Area
90 {
91  MemBuf mb;
92  mb.init();
93  theMessage.packInto(&mb, true);
94  return Area::FromTempBuffer(mb.content(), mb.contentSize());
95 }
96 
97 // throws on failures
98 void
100 {
102  Must(theMessage.parse(buf.start, buf.size, true, &error));
103 }
104 
107 {
108  if (name.assignedHostId())
109  return static_cast<Http::HdrType>(name.hostId());
110  return Http::HdrType::OTHER;
111 }
112 
113 /* FirstLineRep */
114 
116 {
117 }
118 
119 libecap::Version
121 {
122  return libecap::Version(theMessage.http_ver.major,
123  theMessage.http_ver.minor);
124 }
125 
126 void
127 Adaptation::Ecap::FirstLineRep::version(const libecap::Version &aVersion)
128 {
129  theMessage.http_ver.major = aVersion.majr;
130  theMessage.http_ver.minor = aVersion.minr;
131 }
132 
133 libecap::Name
135 {
136  // TODO: optimize?
137  switch (theMessage.http_ver.protocol) {
138  case AnyP::PROTO_HTTP:
139  return libecap::protocolHttp;
140  case AnyP::PROTO_HTTPS:
141  return libecap::protocolHttps;
142  case AnyP::PROTO_FTP:
143  return libecap::protocolFtp;
144  case AnyP::PROTO_GOPHER:
145  return libecap::protocolGopher;
146  case AnyP::PROTO_WAIS:
147  return libecap::protocolWais;
148  case AnyP::PROTO_WHOIS:
149  return libecap::protocolWhois;
150  case AnyP::PROTO_URN:
151  return libecap::protocolUrn;
152  case AnyP::PROTO_ICP:
153  return protocolIcp;
154 #if USE_HTCP
155  case AnyP::PROTO_HTCP:
156  return protocolHtcp;
157 #endif
159  return protocolCacheObj;
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, URL::parse will assume it is not connect;
207  // Can we change URL::parse API to remove the method parameter?
208  const char *buf = aUri.toString().c_str();
209  const bool ok = theMessage.url.parse(theMessage.method, buf);
210  Must(ok);
211 }
212 
215 {
216  const SBuf &fullUrl = theMessage.effectiveRequestUri();
217  // XXX: effectiveRequestUri() cannot return NULL or even empty string, some other problem?
218  Must(!fullUrl.isEmpty());
219  // optimize: avoid copying by having an Area::Detail that locks theMessage
220  return Area::FromTempBuffer(fullUrl.rawContent(), fullUrl.length());
221 }
222 
223 void
225 {
226  if (aMethod.assignedHostId()) {
227  const int id = aMethod.hostId();
229  Must(id != Http::METHOD_OTHER);
230  theMessage.method = HttpRequestMethod(static_cast<Http::MethodType>(id));
231  } else {
232  const std::string &image = aMethod.image();
233  theMessage.method.HttpRequestMethodXXX(image.c_str());
234  }
235 }
236 
239 {
240  switch (theMessage.method.id()) {
241  case Http::METHOD_GET:
242  return libecap::methodGet;
243  case Http::METHOD_POST:
244  return libecap::methodPost;
245  case Http::METHOD_PUT:
246  return libecap::methodPut;
247  case Http::METHOD_HEAD:
248  return libecap::methodHead;
250  return libecap::methodConnect;
251  case Http::METHOD_DELETE:
252  return libecap::methodDelete;
253  case Http::METHOD_TRACE:
254  return libecap::methodTrace;
255  default:
256  return Name(theMessage.method.image().toStdString());
257  }
258 }
259 
260 libecap::Version
262 {
263  return FirstLineRep::version();
264 }
265 
266 void
267 Adaptation::Ecap::RequestLineRep::version(const libecap::Version &aVersion)
268 {
269  FirstLineRep::version(aVersion);
270 }
271 
272 libecap::Name
274 {
275  return FirstLineRep::protocol();
276 }
277 
278 void
280 {
282 }
283 
284 /* ReplyHeaderRep */
285 
287  FirstLineRep(aMessage), theMessage(aMessage)
288 {
289 }
290 
291 void
293 {
294  theMessage.sline.set(theMessage.sline.version, static_cast<Http::StatusCode>(code), nullptr);
295 }
296 
297 int
299 {
300  // TODO: remove cast when possible
301  return static_cast<int>(theMessage.sline.status());
302 }
303 
304 void
306 {
307  // Squid does not support external custom reason phrases so we have
308  // to just reset it (in case there was a custom internal reason set)
309  theMessage.sline.resetReason();
310 }
311 
314 {
315  return Area::FromTempString(std::string(theMessage.sline.reason()));
316 }
317 
318 libecap::Version
320 {
321  return FirstLineRep::version();
322 }
323 
324 void
325 Adaptation::Ecap::StatusLineRep::version(const libecap::Version &aVersion)
326 {
327  FirstLineRep::version(aVersion);
328 }
329 
330 libecap::Name
332 {
333  return FirstLineRep::protocol();
334 }
335 
336 void
338 {
340 }
341 
342 /* BodyRep */
343 
345 {
346 }
347 
348 void
350 {
351  Must(!theBody);
352  Must(aBody != NULL);
353  theBody = aBody;
354 }
355 
358 {
359  return (theBody != nullptr && theBody->bodySizeKnown()) ? BodySize(theBody->bodySize()) : BodySize();
360 }
361 
362 /* MessageRep */
363 
365  theMessage(rawHeader), theFirstLineRep(NULL),
366  theHeaderRep(NULL), theBodyRep(NULL)
367 {
368  Must(theMessage.header); // we do not want to represent a missing message
369 
370  if (HttpRequest *req = dynamic_cast<HttpRequest*>(theMessage.header))
371  theFirstLineRep = new RequestLineRep(*req);
372  else if (HttpReply *rep = dynamic_cast<HttpReply*>(theMessage.header))
373  theFirstLineRep = new StatusLineRep(*rep);
374  else
375  Must(false); // unknown message header type
376 
378 
379  if (theMessage.body_pipe != NULL)
381 }
382 
384 {
385  delete theBodyRep;
386  delete theHeaderRep;
387  delete theFirstLineRep;
388 }
389 
390 libecap::shared_ptr<libecap::Message>
392 {
393  Http::Message *hdr = theMessage.header->clone();
394  hdr->body_pipe = NULL; // if any; TODO: remove pipe cloning from ::clone?
395  libecap::shared_ptr<libecap::Message> res(new MessageRep(hdr));
396 
397  // restore indication of a body if needed, but not the pipe
398  if (theMessage.header->body_pipe != NULL)
399  res->addBody();
400 
401  return res;
402 }
403 
404 libecap::FirstLine &
406 {
407  return *theFirstLineRep;
408 }
409 
410 const libecap::FirstLine &
412 {
413  return *theFirstLineRep;
414 }
415 
416 libecap::Header &
418 {
419  return *theHeaderRep;
420 }
421 
422 const libecap::Header &
424 {
425  return *theHeaderRep;
426 }
427 
428 libecap::Body *
430 {
431  return theBodyRep;
432 }
433 
434 void
436 {
437  Must(!theBodyRep);
438  Must(!theMessage.body_pipe); // set in tieBody()
439  theBodyRep = new BodyRep(NULL);
440 }
441 
442 void
444 {
445  Must(theBodyRep != NULL); // addBody must be called first
446  Must(!theMessage.header->body_pipe);
447  Must(!theMessage.body_pipe);
448  theMessage.header->body_pipe = new BodyPipe(x);
449  theMessage.body_pipe = theMessage.header->body_pipe;
450  theBodyRep->tie(theMessage.body_pipe);
451 }
452 
453 const libecap::Body *Adaptation::Ecap::MessageRep::body() const
454 {
455  return theBodyRep;
456 }
457 
BodyRep(const BodyPipe::Pointer &aBody)
Definition: MessageRep.cc:344
virtual void visitEach(libecap::NamedValueVisitor &visitor) const
Definition: MessageRep.cc:78
const libecap::Name protocolHtcp
#define HttpHeaderInitPos
Definition: HttpHeader.h:48
virtual Value value(const Name &name) const
Definition: MessageRep.cc:42
libecap::BodySize BodySize
Definition: MessageRep.h:132
Definition: SBuf.h:87
virtual Area reasonPhrase() const
Definition: MessageRep.cc:313
void error(char *format,...)
virtual libecap::FirstLine & firstLine()
Definition: MessageRep.cc:405
libecap::Version version() const
Definition: MessageRep.cc:120
void tie(const BodyPipe::Pointer &aBody)
Definition: MessageRep.cc:349
virtual void removeAny(const Name &name)
Definition: MessageRep.cc:65
virtual libecap::shared_ptr< libecap::Message > clone() const
Definition: MessageRep.cc:391
int64_t getInt64() const
Definition: HttpHeader.cc:1538
bool isEmpty() const
Definition: SBuf.h:422
char * p
Definition: membanger.c:43
virtual libecap::Body * body()
Definition: MessageRep.cc:429
virtual Name protocol() const
Definition: MessageRep.cc:331
virtual Area uri() const
Definition: MessageRep.cc:214
size_type size() const
Definition: SquidString.h:71
virtual libecap::Header & header()
Definition: MessageRep.cc:417
virtual Area image() const
Definition: MessageRep.cc:89
void init(mb_size_t szInit, mb_size_t szMax)
Definition: MemBuf.cc:105
const libecap::Name protocolUnknown
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:405
StatusCode
Definition: StatusCode.h:20
const libecap::Name protocolIcy
char const * termedBuf() const
Definition: SquidString.h:90
virtual void add(const Name &name, const Value &value)
Definition: MessageRep.cc:53
static AnyP::ProtocolType TranslateProtocolId(const Name &name)
Definition: MessageRep.cc:189
common parts of HttpRequest and HttpReply
Definition: Message.h:24
virtual int statusCode() const
Definition: MessageRep.cc:298
libecap::FirstLine * theFirstLineRep
Definition: MessageRep.h:170
const libecap::Name protocolCacheObj
const char * c_str()
Definition: SBuf.cc:546
FirstLineRep(Http::Message &aMessage)
Definition: MessageRep.cc:115
void tieBody(Ecap::XactionRep *x)
Definition: MessageRep.cc:443
virtual Name protocol() const
Definition: MessageRep.cc:273
char * content()
start of the added data
Definition: MemBuf.h:41
unsigned char code
Definition: html_quote.c:20
void const char * buf
Definition: stub_helper.cc:16
ssize_t HttpHeaderPos
Definition: HttpHeader.h:45
StatusLineRep(HttpReply &aMessage)
Definition: MessageRep.cc:286
mb_size_t contentSize() const
available data size
Definition: MemBuf.h:47
#define Must(cond)
Definition: TextException.h:89
HttpHeader header
Definition: Message.h:74
virtual libecap::Version version() const
Definition: MessageRep.cc:319
BodyPipePointer body_pipe
Definition: Message.h:46
virtual bool hasAny(const Name &name) const
Definition: MessageRep.cc:33
virtual BodySize bodySize() const
Definition: MessageRep.cc:357
static Http::HdrType TranslateHeaderId(const Name &name)
Definition: MessageRep.cc:106
ProtocolType
Definition: ProtocolType.h:22
Definition: MemBuf.h:23
BodyPipe::Pointer body_pipe
optional pipeline to receive message body
Definition: Message.h:97
HeaderRep(Http::Message &aMessage)
Definition: MessageRep.cc:27
Adaptation::Message theMessage
Definition: MessageRep.h:169
const libecap::Name protocolIcp
MessageRep(Http::Message *rawHeader)
Definition: MessageRep.cc:364
const char * rawContent() const
Definition: SBuf.cc:539
virtual libecap::Version version() const
Definition: MessageRep.cc:261
virtual Name method() const
Definition: MessageRep.cc:238
RequestLineRep(HttpRequest &aMessage)
Definition: MessageRep.cc:198
#define NULL
Definition: types.h:166
virtual void parse(const Area &buf)
Definition: MessageRep.cc:99
Header * header
Definition: Message.h:42

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors