]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/ecap/MessageRep.cc
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 93 eCAP Interface */
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 */
20 #include "adaptation/ecap/MessageRep.h"
21 #include "adaptation/ecap/XactionRep.h"
22 #include "base/TextException.h"
27 Adaptation::Ecap::HeaderRep::HeaderRep(HttpMsg
&aMessage
): theHeader(aMessage
.header
),
33 Adaptation::Ecap::HeaderRep::hasAny(const Name
&name
) const
35 const http_hdr_type squidId
= TranslateHeaderId(name
);
36 // XXX: optimize to remove getByName: we do not need the value here
37 return squidId
== HDR_OTHER
?
38 theHeader
.getByName(name
.image().c_str()).size() > 0:
39 (bool)theHeader
.has(squidId
);
42 Adaptation::Ecap::HeaderRep::Value
43 Adaptation::Ecap::HeaderRep::value(const Name
&name
) const
45 const http_hdr_type squidId
= TranslateHeaderId(name
);
46 const String value
= squidId
== HDR_OTHER
?
47 theHeader
.getByName(name
.image().c_str()) :
48 theHeader
.getStrOrList(squidId
);
49 return value
.size() > 0 ?
50 Value::FromTempString(value
.termedBuf()) : Value();
54 Adaptation::Ecap::HeaderRep::add(const Name
&name
, const Value
&value
)
56 const http_hdr_type squidId
= TranslateHeaderId(name
); // HDR_OTHER OK
57 HttpHeaderEntry
*e
= new HttpHeaderEntry(squidId
, name
.image().c_str(),
58 value
.toString().c_str());
59 theHeader
.addEntry(e
);
61 if (squidId
== HDR_CONTENT_LENGTH
)
62 theMessage
.content_length
= theHeader
.getInt64(HDR_CONTENT_LENGTH
);
66 Adaptation::Ecap::HeaderRep::removeAny(const Name
&name
)
68 const http_hdr_type squidId
= TranslateHeaderId(name
);
69 if (squidId
== HDR_OTHER
)
70 theHeader
.delByName(name
.image().c_str());
72 theHeader
.delById(squidId
);
74 if (squidId
== HDR_CONTENT_LENGTH
)
75 theMessage
.content_length
= theHeader
.getInt64(HDR_CONTENT_LENGTH
);
79 Adaptation::Ecap::HeaderRep::visitEach(libecap::NamedValueVisitor
&visitor
) const
81 HttpHeaderPos pos
= HttpHeaderInitPos
;
82 while (HttpHeaderEntry
*e
= theHeader
.getEntry(&pos
)) {
83 const Name
name(e
->name
.termedBuf()); // optimize: find std Names
84 name
.assignHostId(e
->id
);
85 visitor
.visit(name
, Value(e
->value
.rawBuf(), e
->value
.size()));
90 Adaptation::Ecap::HeaderRep::image() const
96 packerToMemInit(&p
, &mb
);
97 theMessage
.packInto(&p
, true);
99 return Area::FromTempBuffer(mb
.content(), mb
.contentSize());
102 // throws on failures
104 Adaptation::Ecap::HeaderRep::parse(const Area
&buf
)
108 mb
.append(buf
.start
, buf
.size
);
109 Http::StatusCode error
;
110 Must(theMessage
.parse(&mb
, true, &error
));
114 Adaptation::Ecap::HeaderRep::TranslateHeaderId(const Name
&name
)
116 if (name
.assignedHostId())
117 return static_cast<http_hdr_type
>(name
.hostId());
123 Adaptation::Ecap::FirstLineRep::FirstLineRep(HttpMsg
&aMessage
): theMessage(aMessage
)
128 Adaptation::Ecap::FirstLineRep::version() const
130 return libecap::Version(theMessage
.http_ver
.major
,
131 theMessage
.http_ver
.minor
);
135 Adaptation::Ecap::FirstLineRep::version(const libecap::Version
&aVersion
)
137 theMessage
.http_ver
.major
= aVersion
.majr
;
138 theMessage
.http_ver
.minor
= aVersion
.minr
;
142 Adaptation::Ecap::FirstLineRep::protocol() const
145 switch (theMessage
.http_ver
.protocol
) {
146 case AnyP::PROTO_HTTP
:
147 return libecap::protocolHttp
;
148 case AnyP::PROTO_HTTPS
:
149 return libecap::protocolHttps
;
150 case AnyP::PROTO_FTP
:
151 return libecap::protocolFtp
;
152 case AnyP::PROTO_GOPHER
:
153 return libecap::protocolGopher
;
154 case AnyP::PROTO_WAIS
:
155 return libecap::protocolWais
;
156 case AnyP::PROTO_WHOIS
:
157 return libecap::protocolWhois
;
158 case AnyP::PROTO_URN
:
159 return libecap::protocolUrn
;
160 case AnyP::PROTO_ICP
:
163 case AnyP::PROTO_HTCP
:
166 case AnyP::PROTO_CACHE_OBJECT
:
167 return protocolCacheObj
;
168 case AnyP::PROTO_ICY
:
170 case AnyP::PROTO_COAP
:
171 case AnyP::PROTO_COAPS
: // use 'unknown' until libecap supports coap:// and coaps://
172 case AnyP::PROTO_UNKNOWN
:
173 return protocolUnknown
; // until we remember the protocol image
174 case AnyP::PROTO_NONE
:
177 case AnyP::PROTO_MAX
:
178 break; // should not happen
179 // no default to catch AnyP::PROTO_ additions
181 Must(false); // not reached
186 Adaptation::Ecap::FirstLineRep::protocol(const Name
&p
)
188 // TODO: what happens if we fail to translate some protocol?
189 theMessage
.http_ver
.protocol
= TranslateProtocolId(p
);
193 Adaptation::Ecap::FirstLineRep::TranslateProtocolId(const Name
&name
)
195 if (name
.assignedHostId())
196 return static_cast<AnyP::ProtocolType
>(name
.hostId());
197 return AnyP::PROTO_UNKNOWN
;
200 /* RequestHeaderRep */
202 Adaptation::Ecap::RequestLineRep::RequestLineRep(HttpRequest
&aMessage
):
203 FirstLineRep(aMessage
), theMessage(aMessage
)
208 Adaptation::Ecap::RequestLineRep::uri(const Area
&aUri
)
210 // TODO: if method is not set, urlPath will assume it is not connect;
211 // Can we change urlParse API to remove the method parameter?
212 // TODO: optimize: urlPath should take constant URL buffer
213 char *buf
= xstrdup(aUri
.toString().c_str());
214 const bool ok
= urlParse(theMessage
.method
, buf
, &theMessage
);
219 Adaptation::Ecap::RequestLineRep::Area
220 Adaptation::Ecap::RequestLineRep::uri() const
222 const char *fullUrl
= urlCanonical(&theMessage
);
224 // optimize: avoid copying by having an Area::Detail that locks theMessage
225 return Area::FromTempBuffer(fullUrl
, strlen(fullUrl
));
229 Adaptation::Ecap::RequestLineRep::method(const Name
&aMethod
)
231 if (aMethod
.assignedHostId()) {
232 const int id
= aMethod
.hostId();
233 Must(Http::METHOD_NONE
< id
&& id
< Http::METHOD_ENUM_END
);
234 Must(id
!= Http::METHOD_OTHER
);
235 theMessage
.method
= HttpRequestMethod(static_cast<Http::MethodType
>(id
));
237 const std::string
&image
= aMethod
.image();
238 theMessage
.method
.HttpRequestMethodXXX(image
.c_str());
242 Adaptation::Ecap::RequestLineRep::Name
243 Adaptation::Ecap::RequestLineRep::method() const
245 switch (theMessage
.method
.id()) {
246 case Http::METHOD_GET
:
247 return libecap::methodGet
;
248 case Http::METHOD_POST
:
249 return libecap::methodPost
;
250 case Http::METHOD_PUT
:
251 return libecap::methodPut
;
252 case Http::METHOD_HEAD
:
253 return libecap::methodHead
;
254 case Http::METHOD_CONNECT
:
255 return libecap::methodConnect
;
256 case Http::METHOD_DELETE
:
257 return libecap::methodDelete
;
258 case Http::METHOD_TRACE
:
259 return libecap::methodTrace
;
261 return Name(theMessage
.method
.image().toStdString());
266 Adaptation::Ecap::RequestLineRep::version() const
268 return FirstLineRep::version();
272 Adaptation::Ecap::RequestLineRep::version(const libecap::Version
&aVersion
)
274 FirstLineRep::version(aVersion
);
278 Adaptation::Ecap::RequestLineRep::protocol() const
280 return FirstLineRep::protocol();
284 Adaptation::Ecap::RequestLineRep::protocol(const Name
&p
)
286 FirstLineRep::protocol(p
);
291 Adaptation::Ecap::StatusLineRep::StatusLineRep(HttpReply
&aMessage
):
292 FirstLineRep(aMessage
), theMessage(aMessage
)
297 Adaptation::Ecap::StatusLineRep::statusCode(int code
)
299 theMessage
.sline
.set(theMessage
.sline
.version
, static_cast<Http::StatusCode
>(code
), theMessage
.sline
.reason());
303 Adaptation::Ecap::StatusLineRep::statusCode() const
305 // TODO: remove cast when possible
306 return static_cast<int>(theMessage
.sline
.status());
310 Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area
&str
)
312 theMessage
.sline
.set(theMessage
.sline
.version
, theMessage
.sline
.status(), str
.toString().c_str());
315 Adaptation::Ecap::StatusLineRep::Area
316 Adaptation::Ecap::StatusLineRep::reasonPhrase() const
318 return Area::FromTempString(std::string(theMessage
.sline
.reason()));
322 Adaptation::Ecap::StatusLineRep::version() const
324 return FirstLineRep::version();
328 Adaptation::Ecap::StatusLineRep::version(const libecap::Version
&aVersion
)
330 FirstLineRep::version(aVersion
);
334 Adaptation::Ecap::StatusLineRep::protocol() const
336 return FirstLineRep::protocol();
340 Adaptation::Ecap::StatusLineRep::protocol(const Name
&p
)
342 FirstLineRep::protocol(p
);
347 Adaptation::Ecap::BodyRep::BodyRep(const BodyPipe::Pointer
&aBody
): theBody(aBody
)
352 Adaptation::Ecap::BodyRep::tie(const BodyPipe::Pointer
&aBody
)
359 Adaptation::Ecap::BodyRep::BodySize
360 Adaptation::Ecap::BodyRep::bodySize() const
362 return !theBody
? BodySize() : BodySize(theBody
->bodySize());
367 Adaptation::Ecap::MessageRep::MessageRep(HttpMsg
*rawHeader
):
368 theMessage(rawHeader
), theFirstLineRep(NULL
),
369 theHeaderRep(NULL
), theBodyRep(NULL
)
371 Must(theMessage
.header
); // we do not want to represent a missing message
373 if (HttpRequest
*req
= dynamic_cast<HttpRequest
*>(theMessage
.header
))
374 theFirstLineRep
= new RequestLineRep(*req
);
375 else if (HttpReply
*rep
= dynamic_cast<HttpReply
*>(theMessage
.header
))
376 theFirstLineRep
= new StatusLineRep(*rep
);
378 Must(false); // unknown message header type
380 theHeaderRep
= new HeaderRep(*theMessage
.header
);
382 if (theMessage
.body_pipe
!= NULL
)
383 theBodyRep
= new BodyRep(theMessage
.body_pipe
);
386 Adaptation::Ecap::MessageRep::~MessageRep()
390 delete theFirstLineRep
;
393 libecap::shared_ptr
<libecap::Message
>
394 Adaptation::Ecap::MessageRep::clone() const
396 HttpMsg
*hdr
= theMessage
.header
->clone();
397 hdr
->body_pipe
= NULL
; // if any; TODO: remove pipe cloning from ::clone?
398 libecap::shared_ptr
<libecap::Message
> res(new MessageRep(hdr
));
400 // restore indication of a body if needed, but not the pipe
401 if (theMessage
.header
->body_pipe
!= NULL
)
408 Adaptation::Ecap::MessageRep::firstLine()
410 return *theFirstLineRep
;
413 const libecap::FirstLine
&
414 Adaptation::Ecap::MessageRep::firstLine() const
416 return *theFirstLineRep
;
420 Adaptation::Ecap::MessageRep::header()
422 return *theHeaderRep
;
425 const libecap::Header
&
426 Adaptation::Ecap::MessageRep::header() const
428 return *theHeaderRep
;
432 Adaptation::Ecap::MessageRep::body()
438 Adaptation::Ecap::MessageRep::addBody()
441 Must(!theMessage
.body_pipe
); // set in tieBody()
442 theBodyRep
= new BodyRep(NULL
);
446 Adaptation::Ecap::MessageRep::tieBody(Adaptation::Ecap::XactionRep
*x
)
448 Must(theBodyRep
!= NULL
); // addBody must be called first
449 Must(!theMessage
.header
->body_pipe
);
450 Must(!theMessage
.body_pipe
);
451 theMessage
.header
->body_pipe
= new BodyPipe(x
);
452 theMessage
.body_pipe
= theMessage
.header
->body_pipe
;
453 theBodyRep
->tie(theMessage
.body_pipe
);
456 const libecap::Body
*Adaptation::Ecap::MessageRep::body() const