]>
Commit | Line | Data |
---|---|---|
fdc96a39 | 1 | /* |
b510f3a1 | 2 | * DEBUG: section 93 eCAP Interface |
fdc96a39 | 3 | */ |
f7f3304a | 4 | #include "squid-old.h" |
cf331c99 AR |
5 | #include "HttpRequest.h" |
6 | #include "HttpReply.h" | |
7 | #include "BodyPipe.h" | |
cf331c99 AR |
8 | #include <libecap/common/names.h> |
9 | #include <libecap/common/area.h> | |
10 | #include <libecap/common/version.h> | |
12a410c3 | 11 | #include <libecap/common/named_values.h> |
1f3c65fc AR |
12 | #include "adaptation/ecap/MessageRep.h" |
13 | #include "adaptation/ecap/XactionRep.h" | |
14 | #include "adaptation/ecap/Host.h" /* for protocol constants */ | |
3d93a84d | 15 | #include "base/TextException.h" |
fdc96a39 | 16 | |
cf331c99 AR |
17 | /* HeaderRep */ |
18 | ||
574b508c | 19 | Adaptation::Ecap::HeaderRep::HeaderRep(HttpMsg &aMessage): theHeader(aMessage.header), |
26ac0430 | 20 | theMessage(aMessage) |
cf331c99 AR |
21 | { |
22 | } | |
23 | ||
cf331c99 | 24 | bool |
574b508c | 25 | Adaptation::Ecap::HeaderRep::hasAny(const Name &name) const |
cf331c99 AR |
26 | { |
27 | const http_hdr_type squidId = TranslateHeaderId(name); | |
28 | // XXX: optimize to remove getByName: we do not need the value here | |
29 | return squidId == HDR_OTHER ? | |
26ac0430 AJ |
30 | theHeader.getByName(name.image().c_str()).size() > 0: |
31 | (bool)theHeader.has(squidId); | |
cf331c99 AR |
32 | } |
33 | ||
574b508c AR |
34 | Adaptation::Ecap::HeaderRep::Value |
35 | Adaptation::Ecap::HeaderRep::value(const Name &name) const | |
cf331c99 AR |
36 | { |
37 | const http_hdr_type squidId = TranslateHeaderId(name); | |
38 | const String value = squidId == HDR_OTHER ? | |
26ac0430 AJ |
39 | theHeader.getByName(name.image().c_str()) : |
40 | theHeader.getStrOrList(squidId); | |
5e6f9b92 | 41 | return value.defined() ? |
001eaf80 | 42 | Value::FromTempString(value.termedBuf()) : Value(); |
cf331c99 AR |
43 | } |
44 | ||
45 | void | |
574b508c | 46 | Adaptation::Ecap::HeaderRep::add(const Name &name, const Value &value) |
cf331c99 AR |
47 | { |
48 | const http_hdr_type squidId = TranslateHeaderId(name); // HDR_OTHER OK | |
49 | HttpHeaderEntry *e = new HttpHeaderEntry(squidId, name.image().c_str(), | |
26ac0430 | 50 | value.toString().c_str()); |
cf331c99 | 51 | theHeader.addEntry(e); |
809fd5d3 AJ |
52 | |
53 | if (squidId == HDR_CONTENT_LENGTH) | |
74174c03 | 54 | theMessage.content_length = theHeader.getInt64(HDR_CONTENT_LENGTH); |
cf331c99 AR |
55 | } |
56 | ||
57 | void | |
574b508c | 58 | Adaptation::Ecap::HeaderRep::removeAny(const Name &name) |
cf331c99 AR |
59 | { |
60 | const http_hdr_type squidId = TranslateHeaderId(name); | |
61 | if (squidId == HDR_OTHER) | |
62 | theHeader.delByName(name.image().c_str()); | |
63 | else | |
64 | theHeader.delById(squidId); | |
809fd5d3 AJ |
65 | |
66 | if (squidId == HDR_CONTENT_LENGTH) | |
74174c03 | 67 | theMessage.content_length = theHeader.getInt64(HDR_CONTENT_LENGTH); |
cf331c99 AR |
68 | } |
69 | ||
12a410c3 AR |
70 | void |
71 | Adaptation::Ecap::HeaderRep::visitEach(libecap::NamedValueVisitor &visitor) const | |
72 | { | |
73 | HttpHeaderPos pos = HttpHeaderInitPos; | |
74 | while (HttpHeaderEntry *e = theHeader.getEntry(&pos)) { | |
75 | const Name name(e->name.termedBuf()); // optimize: find std Names | |
76 | name.assignHostId(e->id); | |
77 | visitor.visit(name, Value(e->value.rawBuf(), e->value.size())); | |
78 | } | |
79 | } | |
80 | ||
cf331c99 | 81 | libecap::Area |
574b508c | 82 | Adaptation::Ecap::HeaderRep::image() const |
cf331c99 AR |
83 | { |
84 | MemBuf mb; | |
85 | mb.init(); | |
86 | ||
87 | Packer p; | |
88 | packerToMemInit(&p, &mb); | |
89 | theMessage.packInto(&p, true); | |
90 | packerClean(&p); | |
91 | return Area::FromTempBuffer(mb.content(), mb.contentSize()); | |
92 | } | |
93 | ||
94 | // throws on failures | |
95 | void | |
574b508c | 96 | Adaptation::Ecap::HeaderRep::parse(const Area &buf) |
cf331c99 AR |
97 | { |
98 | MemBuf mb; | |
99 | mb.init(); | |
100 | mb.append(buf.start, buf.size); | |
101 | http_status error; | |
102 | Must(theMessage.parse(&mb, true, &error)); | |
103 | } | |
104 | ||
77773405 | 105 | http_hdr_type |
574b508c | 106 | Adaptation::Ecap::HeaderRep::TranslateHeaderId(const Name &name) |
77773405 AR |
107 | { |
108 | if (name.assignedHostId()) | |
109 | return static_cast<http_hdr_type>(name.hostId()); | |
110 | return HDR_OTHER; | |
111 | } | |
112 | ||
113 | ||
114 | /* FirstLineRep */ | |
115 | ||
574b508c | 116 | Adaptation::Ecap::FirstLineRep::FirstLineRep(HttpMsg &aMessage): theMessage(aMessage) |
77773405 AR |
117 | { |
118 | } | |
119 | ||
cf331c99 | 120 | libecap::Version |
574b508c | 121 | Adaptation::Ecap::FirstLineRep::version() const |
cf331c99 AR |
122 | { |
123 | return libecap::Version(theMessage.http_ver.major, | |
26ac0430 | 124 | theMessage.http_ver.minor); |
cf331c99 AR |
125 | } |
126 | ||
127 | void | |
574b508c | 128 | Adaptation::Ecap::FirstLineRep::version(const libecap::Version &aVersion) |
cf331c99 AR |
129 | { |
130 | theMessage.http_ver.major = aVersion.majr; | |
131 | theMessage.http_ver.minor = aVersion.minr; | |
132 | } | |
133 | ||
134 | libecap::Name | |
574b508c | 135 | Adaptation::Ecap::FirstLineRep::protocol() const |
cf331c99 AR |
136 | { |
137 | // TODO: optimize? | |
138 | switch (theMessage.protocol) { | |
39a19cb7 | 139 | case AnyP::PROTO_HTTP: |
26ac0430 | 140 | return libecap::protocolHttp; |
39a19cb7 | 141 | case AnyP::PROTO_HTTPS: |
26ac0430 | 142 | return libecap::protocolHttps; |
39a19cb7 | 143 | case AnyP::PROTO_FTP: |
26ac0430 | 144 | return libecap::protocolFtp; |
39a19cb7 | 145 | case AnyP::PROTO_GOPHER: |
26ac0430 | 146 | return libecap::protocolGopher; |
39a19cb7 | 147 | case AnyP::PROTO_WAIS: |
26ac0430 | 148 | return libecap::protocolWais; |
39a19cb7 | 149 | case AnyP::PROTO_WHOIS: |
26ac0430 | 150 | return libecap::protocolWhois; |
39a19cb7 | 151 | case AnyP::PROTO_URN: |
26ac0430 | 152 | return libecap::protocolUrn; |
39a19cb7 | 153 | case AnyP::PROTO_ICP: |
26ac0430 | 154 | return protocolIcp; |
cf331c99 | 155 | #if USE_HTCP |
39a19cb7 | 156 | case AnyP::PROTO_HTCP: |
26ac0430 | 157 | return protocolHtcp; |
cf331c99 | 158 | #endif |
39a19cb7 | 159 | case AnyP::PROTO_CACHE_OBJECT: |
26ac0430 | 160 | return protocolCacheObj; |
39a19cb7 | 161 | case AnyP::PROTO_INTERNAL: |
26ac0430 | 162 | return protocolInternal; |
39a19cb7 | 163 | case AnyP::PROTO_ICY: |
555aedbf AR |
164 | return protocolIcy; |
165 | case AnyP::PROTO_UNKNOWN: | |
166 | return protocolUnknown; // until we remember the protocol image | |
39a19cb7 | 167 | case AnyP::PROTO_NONE: |
26ac0430 AJ |
168 | return Name(); |
169 | ||
39a19cb7 | 170 | case AnyP::PROTO_MAX: |
26ac0430 | 171 | break; // should not happen |
39a19cb7 | 172 | // no default to catch AnyP::PROTO_ additions |
cf331c99 AR |
173 | } |
174 | Must(false); // not reached | |
175 | return Name(); | |
176 | } | |
177 | ||
178 | void | |
574b508c | 179 | Adaptation::Ecap::FirstLineRep::protocol(const Name &p) |
cf331c99 AR |
180 | { |
181 | // TODO: what happens if we fail to translate some protocol? | |
182 | theMessage.protocol = TranslateProtocolId(p); | |
183 | } | |
184 | ||
555aedbf | 185 | AnyP::ProtocolType |
574b508c | 186 | Adaptation::Ecap::FirstLineRep::TranslateProtocolId(const Name &name) |
77773405 AR |
187 | { |
188 | if (name.assignedHostId()) | |
555aedbf AR |
189 | return static_cast<AnyP::ProtocolType>(name.hostId()); |
190 | return AnyP::PROTO_UNKNOWN; | |
77773405 AR |
191 | } |
192 | ||
cf331c99 AR |
193 | |
194 | /* RequestHeaderRep */ | |
195 | ||
574b508c | 196 | Adaptation::Ecap::RequestLineRep::RequestLineRep(HttpRequest &aMessage): |
26ac0430 | 197 | FirstLineRep(aMessage), theMessage(aMessage) |
cf331c99 AR |
198 | { |
199 | } | |
200 | ||
201 | void | |
574b508c | 202 | Adaptation::Ecap::RequestLineRep::uri(const Area &aUri) |
cf331c99 AR |
203 | { |
204 | // TODO: if method is not set, urlPath will assume it is not connect; | |
205 | // Can we change urlParse API to remove the method parameter? | |
206 | // TODO: optimize: urlPath should take constant URL buffer | |
207 | char *buf = xstrdup(aUri.toString().c_str()); | |
208 | const bool ok = urlParse(theMessage.method, buf, &theMessage); | |
209 | xfree(buf); | |
210 | Must(ok); | |
211 | } | |
212 | ||
574b508c AR |
213 | Adaptation::Ecap::RequestLineRep::Area |
214 | Adaptation::Ecap::RequestLineRep::uri() const | |
cf331c99 | 215 | { |
dd31ab8f AR |
216 | const char *fullUrl = urlCanonical(&theMessage); |
217 | Must(fullUrl); | |
218 | // optimize: avoid copying by having an Area::Detail that locks theMessage | |
219 | return Area::FromTempBuffer(fullUrl, strlen(fullUrl)); | |
cf331c99 AR |
220 | } |
221 | ||
222 | void | |
574b508c | 223 | Adaptation::Ecap::RequestLineRep::method(const Name &aMethod) |
cf331c99 AR |
224 | { |
225 | if (aMethod.assignedHostId()) { | |
226 | const int id = aMethod.hostId(); | |
227 | Must(METHOD_NONE < id && id < METHOD_ENUM_END); | |
228 | Must(id != METHOD_OTHER); | |
229 | theMessage.method = HttpRequestMethod(static_cast<_method_t>(id)); | |
230 | } else { | |
231 | const std::string &image = aMethod.image(); | |
232 | theMessage.method = HttpRequestMethod(image.data(), | |
26ac0430 | 233 | image.data() + image.size()); |
cf331c99 AR |
234 | } |
235 | } | |
236 | ||
574b508c AR |
237 | Adaptation::Ecap::RequestLineRep::Name |
238 | Adaptation::Ecap::RequestLineRep::method() const | |
cf331c99 AR |
239 | { |
240 | switch (theMessage.method.id()) { | |
26ac0430 AJ |
241 | case METHOD_GET: |
242 | return libecap::methodGet; | |
243 | case METHOD_POST: | |
244 | return libecap::methodPost; | |
245 | case METHOD_PUT: | |
246 | return libecap::methodPut; | |
247 | case METHOD_HEAD: | |
248 | return libecap::methodHead; | |
249 | case METHOD_CONNECT: | |
250 | return libecap::methodConnect; | |
251 | case METHOD_DELETE: | |
252 | return libecap::methodDelete; | |
253 | case METHOD_TRACE: | |
254 | return libecap::methodTrace; | |
255 | default: | |
256 | return Name(theMessage.method.image()); | |
cf331c99 AR |
257 | } |
258 | } | |
259 | ||
77773405 | 260 | libecap::Version |
574b508c | 261 | Adaptation::Ecap::RequestLineRep::version() const |
77773405 AR |
262 | { |
263 | return FirstLineRep::version(); | |
264 | } | |
265 | ||
266 | void | |
574b508c | 267 | Adaptation::Ecap::RequestLineRep::version(const libecap::Version &aVersion) |
77773405 AR |
268 | { |
269 | FirstLineRep::version(aVersion); | |
270 | } | |
271 | ||
272 | libecap::Name | |
574b508c | 273 | Adaptation::Ecap::RequestLineRep::protocol() const |
77773405 AR |
274 | { |
275 | return FirstLineRep::protocol(); | |
276 | } | |
277 | ||
278 | void | |
574b508c | 279 | Adaptation::Ecap::RequestLineRep::protocol(const Name &p) |
77773405 AR |
280 | { |
281 | FirstLineRep::protocol(p); | |
282 | } | |
283 | ||
cf331c99 AR |
284 | |
285 | /* ReplyHeaderRep */ | |
286 | ||
574b508c | 287 | Adaptation::Ecap::StatusLineRep::StatusLineRep(HttpReply &aMessage): |
26ac0430 | 288 | FirstLineRep(aMessage), theMessage(aMessage) |
cf331c99 AR |
289 | { |
290 | } | |
291 | ||
292 | void | |
574b508c | 293 | Adaptation::Ecap::StatusLineRep::statusCode(int code) |
cf331c99 AR |
294 | { |
295 | // TODO: why is .status a enum? Do we not support unknown statuses? | |
296 | theMessage.sline.status = static_cast<http_status>(code); | |
297 | } | |
298 | ||
299 | int | |
574b508c | 300 | Adaptation::Ecap::StatusLineRep::statusCode() const |
cf331c99 AR |
301 | { |
302 | // TODO: see statusCode(code) TODO above | |
303 | return static_cast<int>(theMessage.sline.status); | |
304 | } | |
305 | ||
306 | void | |
574b508c | 307 | Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area &) |
cf331c99 AR |
308 | { |
309 | // Squid does not support custom reason phrases | |
310 | theMessage.sline.reason = NULL; | |
311 | } | |
312 | ||
574b508c AR |
313 | Adaptation::Ecap::StatusLineRep::Area |
314 | Adaptation::Ecap::StatusLineRep::reasonPhrase() const | |
cf331c99 AR |
315 | { |
316 | return theMessage.sline.reason ? | |
26ac0430 | 317 | Area::FromTempString(std::string(theMessage.sline.reason)) : Area(); |
cf331c99 AR |
318 | } |
319 | ||
77773405 | 320 | libecap::Version |
574b508c | 321 | Adaptation::Ecap::StatusLineRep::version() const |
77773405 AR |
322 | { |
323 | return FirstLineRep::version(); | |
324 | } | |
325 | ||
326 | void | |
574b508c | 327 | Adaptation::Ecap::StatusLineRep::version(const libecap::Version &aVersion) |
77773405 AR |
328 | { |
329 | FirstLineRep::version(aVersion); | |
330 | } | |
331 | ||
332 | libecap::Name | |
574b508c | 333 | Adaptation::Ecap::StatusLineRep::protocol() const |
77773405 AR |
334 | { |
335 | return FirstLineRep::protocol(); | |
336 | } | |
337 | ||
338 | void | |
574b508c | 339 | Adaptation::Ecap::StatusLineRep::protocol(const Name &p) |
77773405 AR |
340 | { |
341 | FirstLineRep::protocol(p); | |
342 | } | |
cf331c99 AR |
343 | |
344 | /* BodyRep */ | |
345 | ||
574b508c | 346 | Adaptation::Ecap::BodyRep::BodyRep(const BodyPipe::Pointer &aBody): theBody(aBody) |
cf331c99 AR |
347 | { |
348 | } | |
349 | ||
77773405 | 350 | void |
574b508c | 351 | Adaptation::Ecap::BodyRep::tie(const BodyPipe::Pointer &aBody) |
77773405 AR |
352 | { |
353 | Must(!theBody); | |
354 | Must(aBody != NULL); | |
355 | theBody = aBody; | |
356 | } | |
357 | ||
574b508c AR |
358 | Adaptation::Ecap::BodyRep::BodySize |
359 | Adaptation::Ecap::BodyRep::bodySize() const | |
cf331c99 | 360 | { |
77773405 | 361 | return !theBody ? BodySize() : BodySize(theBody->bodySize()); |
cf331c99 AR |
362 | } |
363 | ||
cf331c99 AR |
364 | |
365 | /* MessageRep */ | |
366 | ||
574b508c | 367 | Adaptation::Ecap::MessageRep::MessageRep(HttpMsg *rawHeader): |
26ac0430 AJ |
368 | theMessage(rawHeader), theFirstLineRep(NULL), |
369 | theHeaderRep(NULL), theBodyRep(NULL) | |
cf331c99 AR |
370 | { |
371 | Must(theMessage.header); // we do not want to represent a missing message | |
372 | ||
373 | if (HttpRequest *req = dynamic_cast<HttpRequest*>(theMessage.header)) | |
77773405 | 374 | theFirstLineRep = new RequestLineRep(*req); |
e1381638 AJ |
375 | else if (HttpReply *rep = dynamic_cast<HttpReply*>(theMessage.header)) |
376 | theFirstLineRep = new StatusLineRep(*rep); | |
cf331c99 | 377 | else |
e1381638 | 378 | Must(false); // unknown message header type |
cf331c99 | 379 | |
77773405 AR |
380 | theHeaderRep = new HeaderRep(*theMessage.header); |
381 | ||
cf331c99 AR |
382 | if (theMessage.body_pipe != NULL) |
383 | theBodyRep = new BodyRep(theMessage.body_pipe); | |
384 | } | |
385 | ||
574b508c | 386 | Adaptation::Ecap::MessageRep::~MessageRep() |
cf331c99 | 387 | { |
77773405 | 388 | delete theBodyRep; |
80031342 AR |
389 | delete theHeaderRep; |
390 | delete theFirstLineRep; | |
77773405 AR |
391 | } |
392 | ||
393 | libecap::shared_ptr<libecap::Message> | |
574b508c | 394 | Adaptation::Ecap::MessageRep::clone() const |
77773405 AR |
395 | { |
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)); | |
399 | ||
400 | // restore indication of a body if needed, but not the pipe | |
401 | if (theMessage.header->body_pipe != NULL) | |
402 | res->addBody(); | |
403 | ||
404 | return res; | |
405 | } | |
406 | ||
407 | libecap::FirstLine & | |
574b508c | 408 | Adaptation::Ecap::MessageRep::firstLine() |
77773405 AR |
409 | { |
410 | return *theFirstLineRep; | |
411 | } | |
412 | ||
413 | const libecap::FirstLine & | |
574b508c | 414 | Adaptation::Ecap::MessageRep::firstLine() const |
77773405 AR |
415 | { |
416 | return *theFirstLineRep; | |
cf331c99 AR |
417 | } |
418 | ||
419 | libecap::Header & | |
574b508c | 420 | Adaptation::Ecap::MessageRep::header() |
cf331c99 AR |
421 | { |
422 | return *theHeaderRep; | |
423 | } | |
424 | ||
425 | const libecap::Header & | |
574b508c | 426 | Adaptation::Ecap::MessageRep::header() const |
cf331c99 AR |
427 | { |
428 | return *theHeaderRep; | |
429 | } | |
430 | ||
431 | libecap::Body * | |
574b508c | 432 | Adaptation::Ecap::MessageRep::body() |
cf331c99 AR |
433 | { |
434 | return theBodyRep; | |
435 | } | |
436 | ||
437 | void | |
574b508c | 438 | Adaptation::Ecap::MessageRep::addBody() |
cf331c99 | 439 | { |
cf331c99 | 440 | Must(!theBodyRep); |
77773405 AR |
441 | Must(!theMessage.body_pipe); // set in tieBody() |
442 | theBodyRep = new BodyRep(NULL); | |
443 | } | |
444 | ||
445 | void | |
574b508c | 446 | Adaptation::Ecap::MessageRep::tieBody(Adaptation::Ecap::XactionRep *x) |
77773405 AR |
447 | { |
448 | Must(theBodyRep != NULL); // addBody must be called first | |
ce367911 | 449 | Must(!theMessage.header->body_pipe); |
cf331c99 | 450 | Must(!theMessage.body_pipe); |
ce367911 AR |
451 | theMessage.header->body_pipe = new BodyPipe(x); |
452 | theMessage.body_pipe = theMessage.header->body_pipe; | |
77773405 | 453 | theBodyRep->tie(theMessage.body_pipe); |
cf331c99 AR |
454 | } |
455 | ||
574b508c | 456 | const libecap::Body *Adaptation::Ecap::MessageRep::body() const |
cf331c99 AR |
457 | { |
458 | return theBodyRep; | |
459 | } |