]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/ecap/MessageRep.cc
2 * DEBUG: section 93 eCAP Interface
5 #include "HttpRequest.h"
8 #include <libecap/common/names.h>
9 #include <libecap/common/area.h>
10 #include <libecap/common/version.h>
11 #include <libecap/common/named_values.h>
12 #include "adaptation/ecap/MessageRep.h"
13 #include "adaptation/ecap/XactionRep.h"
14 #include "adaptation/ecap/Host.h" /* for protocol constants */
15 #include "base/TextException.h"
20 Adaptation::Ecap::HeaderRep::HeaderRep(HttpMsg
&aMessage
): theHeader(aMessage
.header
),
26 Adaptation::Ecap::HeaderRep::hasAny(const Name
&name
) const
28 const http_hdr_type squidId
= TranslateHeaderId(name
);
29 // XXX: optimize to remove getByName: we do not need the value here
30 return squidId
== HDR_OTHER
?
31 theHeader
.getByName(name
.image().c_str()).size() > 0:
32 (bool)theHeader
.has(squidId
);
35 Adaptation::Ecap::HeaderRep::Value
36 Adaptation::Ecap::HeaderRep::value(const Name
&name
) const
38 const http_hdr_type squidId
= TranslateHeaderId(name
);
39 const String value
= squidId
== HDR_OTHER
?
40 theHeader
.getByName(name
.image().c_str()) :
41 theHeader
.getStrOrList(squidId
);
42 return value
.defined() ?
43 Value::FromTempString(value
.termedBuf()) : Value();
47 Adaptation::Ecap::HeaderRep::add(const Name
&name
, const Value
&value
)
49 const http_hdr_type squidId
= TranslateHeaderId(name
); // HDR_OTHER OK
50 HttpHeaderEntry
*e
= new HttpHeaderEntry(squidId
, name
.image().c_str(),
51 value
.toString().c_str());
52 theHeader
.addEntry(e
);
54 if (squidId
== HDR_CONTENT_LENGTH
)
55 theMessage
.content_length
= theHeader
.getInt64(HDR_CONTENT_LENGTH
);
59 Adaptation::Ecap::HeaderRep::removeAny(const Name
&name
)
61 const http_hdr_type squidId
= TranslateHeaderId(name
);
62 if (squidId
== HDR_OTHER
)
63 theHeader
.delByName(name
.image().c_str());
65 theHeader
.delById(squidId
);
67 if (squidId
== HDR_CONTENT_LENGTH
)
68 theMessage
.content_length
= theHeader
.getInt64(HDR_CONTENT_LENGTH
);
72 Adaptation::Ecap::HeaderRep::visitEach(libecap::NamedValueVisitor
&visitor
) const
74 HttpHeaderPos pos
= HttpHeaderInitPos
;
75 while (HttpHeaderEntry
*e
= theHeader
.getEntry(&pos
)) {
76 const Name
name(e
->name
.termedBuf()); // optimize: find std Names
77 name
.assignHostId(e
->id
);
78 visitor
.visit(name
, Value(e
->value
.rawBuf(), e
->value
.size()));
83 Adaptation::Ecap::HeaderRep::image() const
89 packerToMemInit(&p
, &mb
);
90 theMessage
.packInto(&p
, true);
92 return Area::FromTempBuffer(mb
.content(), mb
.contentSize());
97 Adaptation::Ecap::HeaderRep::parse(const Area
&buf
)
101 mb
.append(buf
.start
, buf
.size
);
103 Must(theMessage
.parse(&mb
, true, &error
));
107 Adaptation::Ecap::HeaderRep::TranslateHeaderId(const Name
&name
)
109 if (name
.assignedHostId())
110 return static_cast<http_hdr_type
>(name
.hostId());
116 Adaptation::Ecap::FirstLineRep::FirstLineRep(HttpMsg
&aMessage
): theMessage(aMessage
)
121 Adaptation::Ecap::FirstLineRep::version() const
123 return libecap::Version(theMessage
.http_ver
.major
,
124 theMessage
.http_ver
.minor
);
128 Adaptation::Ecap::FirstLineRep::version(const libecap::Version
&aVersion
)
130 theMessage
.http_ver
.major
= aVersion
.majr
;
131 theMessage
.http_ver
.minor
= aVersion
.minr
;
135 Adaptation::Ecap::FirstLineRep::protocol() const
138 switch (theMessage
.protocol
) {
139 case AnyP::PROTO_HTTP
:
140 return libecap::protocolHttp
;
141 case AnyP::PROTO_HTTPS
:
142 return libecap::protocolHttps
;
143 case AnyP::PROTO_FTP
:
144 return libecap::protocolFtp
;
145 case AnyP::PROTO_GOPHER
:
146 return libecap::protocolGopher
;
147 case AnyP::PROTO_WAIS
:
148 return libecap::protocolWais
;
149 case AnyP::PROTO_WHOIS
:
150 return libecap::protocolWhois
;
151 case AnyP::PROTO_URN
:
152 return libecap::protocolUrn
;
153 case AnyP::PROTO_ICP
:
156 case AnyP::PROTO_HTCP
:
159 case AnyP::PROTO_CACHE_OBJECT
:
160 return protocolCacheObj
;
161 case AnyP::PROTO_INTERNAL
:
162 return protocolInternal
;
163 case AnyP::PROTO_ICY
:
165 case AnyP::PROTO_COAP
:
166 case AnyP::PROTO_COAPS
: // use 'unknown' until libecap supports coap:// and coaps://
167 case AnyP::PROTO_UNKNOWN
:
168 return protocolUnknown
; // until we remember the protocol image
169 case AnyP::PROTO_NONE
:
172 case AnyP::PROTO_MAX
:
173 break; // should not happen
174 // no default to catch AnyP::PROTO_ additions
176 Must(false); // not reached
181 Adaptation::Ecap::FirstLineRep::protocol(const Name
&p
)
183 // TODO: what happens if we fail to translate some protocol?
184 theMessage
.protocol
= TranslateProtocolId(p
);
188 Adaptation::Ecap::FirstLineRep::TranslateProtocolId(const Name
&name
)
190 if (name
.assignedHostId())
191 return static_cast<AnyP::ProtocolType
>(name
.hostId());
192 return AnyP::PROTO_UNKNOWN
;
195 /* RequestHeaderRep */
197 Adaptation::Ecap::RequestLineRep::RequestLineRep(HttpRequest
&aMessage
):
198 FirstLineRep(aMessage
), theMessage(aMessage
)
203 Adaptation::Ecap::RequestLineRep::uri(const Area
&aUri
)
205 // TODO: if method is not set, urlPath will assume it is not connect;
206 // Can we change urlParse API to remove the method parameter?
207 // TODO: optimize: urlPath should take constant URL buffer
208 char *buf
= xstrdup(aUri
.toString().c_str());
209 const bool ok
= urlParse(theMessage
.method
, buf
, &theMessage
);
214 Adaptation::Ecap::RequestLineRep::Area
215 Adaptation::Ecap::RequestLineRep::uri() const
217 const char *fullUrl
= urlCanonical(&theMessage
);
219 // optimize: avoid copying by having an Area::Detail that locks theMessage
220 return Area::FromTempBuffer(fullUrl
, strlen(fullUrl
));
224 Adaptation::Ecap::RequestLineRep::method(const Name
&aMethod
)
226 if (aMethod
.assignedHostId()) {
227 const int id
= aMethod
.hostId();
228 Must(METHOD_NONE
< id
&& id
< METHOD_ENUM_END
);
229 Must(id
!= METHOD_OTHER
);
230 theMessage
.method
= HttpRequestMethod(static_cast<_method_t
>(id
));
232 const std::string
&image
= aMethod
.image();
233 theMessage
.method
= HttpRequestMethod(image
.data(),
234 image
.data() + image
.size());
238 Adaptation::Ecap::RequestLineRep::Name
239 Adaptation::Ecap::RequestLineRep::method() const
241 switch (theMessage
.method
.id()) {
243 return libecap::methodGet
;
245 return libecap::methodPost
;
247 return libecap::methodPut
;
249 return libecap::methodHead
;
251 return libecap::methodConnect
;
253 return libecap::methodDelete
;
255 return libecap::methodTrace
;
257 return Name(theMessage
.method
.image());
262 Adaptation::Ecap::RequestLineRep::version() const
264 return FirstLineRep::version();
268 Adaptation::Ecap::RequestLineRep::version(const libecap::Version
&aVersion
)
270 FirstLineRep::version(aVersion
);
274 Adaptation::Ecap::RequestLineRep::protocol() const
276 return FirstLineRep::protocol();
280 Adaptation::Ecap::RequestLineRep::protocol(const Name
&p
)
282 FirstLineRep::protocol(p
);
287 Adaptation::Ecap::StatusLineRep::StatusLineRep(HttpReply
&aMessage
):
288 FirstLineRep(aMessage
), theMessage(aMessage
)
293 Adaptation::Ecap::StatusLineRep::statusCode(int code
)
295 // TODO: why is .status a enum? Do we not support unknown statuses?
296 theMessage
.sline
.status
= static_cast<http_status
>(code
);
300 Adaptation::Ecap::StatusLineRep::statusCode() const
302 // TODO: see statusCode(code) TODO above
303 return static_cast<int>(theMessage
.sline
.status
);
307 Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area
&)
309 // Squid does not support custom reason phrases
310 theMessage
.sline
.reason
= NULL
;
313 Adaptation::Ecap::StatusLineRep::Area
314 Adaptation::Ecap::StatusLineRep::reasonPhrase() const
316 return theMessage
.sline
.reason
?
317 Area::FromTempString(std::string(theMessage
.sline
.reason
)) : Area();
321 Adaptation::Ecap::StatusLineRep::version() const
323 return FirstLineRep::version();
327 Adaptation::Ecap::StatusLineRep::version(const libecap::Version
&aVersion
)
329 FirstLineRep::version(aVersion
);
333 Adaptation::Ecap::StatusLineRep::protocol() const
335 return FirstLineRep::protocol();
339 Adaptation::Ecap::StatusLineRep::protocol(const Name
&p
)
341 FirstLineRep::protocol(p
);
346 Adaptation::Ecap::BodyRep::BodyRep(const BodyPipe::Pointer
&aBody
): theBody(aBody
)
351 Adaptation::Ecap::BodyRep::tie(const BodyPipe::Pointer
&aBody
)
358 Adaptation::Ecap::BodyRep::BodySize
359 Adaptation::Ecap::BodyRep::bodySize() const
361 return !theBody
? BodySize() : BodySize(theBody
->bodySize());
366 Adaptation::Ecap::MessageRep::MessageRep(HttpMsg
*rawHeader
):
367 theMessage(rawHeader
), theFirstLineRep(NULL
),
368 theHeaderRep(NULL
), theBodyRep(NULL
)
370 Must(theMessage
.header
); // we do not want to represent a missing message
372 if (HttpRequest
*req
= dynamic_cast<HttpRequest
*>(theMessage
.header
))
373 theFirstLineRep
= new RequestLineRep(*req
);
374 else if (HttpReply
*rep
= dynamic_cast<HttpReply
*>(theMessage
.header
))
375 theFirstLineRep
= new StatusLineRep(*rep
);
377 Must(false); // unknown message header type
379 theHeaderRep
= new HeaderRep(*theMessage
.header
);
381 if (theMessage
.body_pipe
!= NULL
)
382 theBodyRep
= new BodyRep(theMessage
.body_pipe
);
385 Adaptation::Ecap::MessageRep::~MessageRep()
389 delete theFirstLineRep
;
392 libecap::shared_ptr
<libecap::Message
>
393 Adaptation::Ecap::MessageRep::clone() const
395 HttpMsg
*hdr
= theMessage
.header
->clone();
396 hdr
->body_pipe
= NULL
; // if any; TODO: remove pipe cloning from ::clone?
397 libecap::shared_ptr
<libecap::Message
> res(new MessageRep(hdr
));
399 // restore indication of a body if needed, but not the pipe
400 if (theMessage
.header
->body_pipe
!= NULL
)
407 Adaptation::Ecap::MessageRep::firstLine()
409 return *theFirstLineRep
;
412 const libecap::FirstLine
&
413 Adaptation::Ecap::MessageRep::firstLine() const
415 return *theFirstLineRep
;
419 Adaptation::Ecap::MessageRep::header()
421 return *theHeaderRep
;
424 const libecap::Header
&
425 Adaptation::Ecap::MessageRep::header() const
427 return *theHeaderRep
;
431 Adaptation::Ecap::MessageRep::body()
437 Adaptation::Ecap::MessageRep::addBody()
440 Must(!theMessage
.body_pipe
); // set in tieBody()
441 theBodyRep
= new BodyRep(NULL
);
445 Adaptation::Ecap::MessageRep::tieBody(Adaptation::Ecap::XactionRep
*x
)
447 Must(theBodyRep
!= NULL
); // addBody must be called first
448 Must(!theMessage
.header
->body_pipe
);
449 Must(!theMessage
.body_pipe
);
450 theMessage
.header
->body_pipe
= new BodyPipe(x
);
451 theMessage
.body_pipe
= theMessage
.header
->body_pipe
;
452 theBodyRep
->tie(theMessage
.body_pipe
);
455 const libecap::Body
*Adaptation::Ecap::MessageRep::body() const