]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/icap/OptXact.cc
Renamed squid.h to squid-old.h and config.h to squid.h
[thirdparty/squid.git] / src / adaptation / icap / OptXact.cc
1 /*
2 * DEBUG: section 93 ICAP (RFC 3507) Client
3 */
4
5 #include "squid-old.h"
6 #include "comm.h"
7 #include "HttpReply.h"
8
9 #include "adaptation/Answer.h"
10 #include "adaptation/icap/OptXact.h"
11 #include "adaptation/icap/Options.h"
12 #include "adaptation/icap/Config.h"
13 #include "base/TextException.h"
14 #include "SquidTime.h"
15 #include "HttpRequest.h"
16
17 CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, OptXact);
18 CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, OptXactLauncher);
19
20
21 Adaptation::Icap::OptXact::OptXact(Adaptation::Icap::ServiceRep::Pointer &aService):
22 AsyncJob("Adaptation::Icap::OptXact"),
23 Adaptation::Icap::Xaction("Adaptation::Icap::OptXact", aService),
24 readAll(false)
25 {
26 }
27
28 void Adaptation::Icap::OptXact::start()
29 {
30 Adaptation::Icap::Xaction::start();
31
32 openConnection();
33 }
34
35 void Adaptation::Icap::OptXact::handleCommConnected()
36 {
37 scheduleRead();
38
39 MemBuf requestBuf;
40 requestBuf.init();
41 makeRequest(requestBuf);
42 debugs(93, 9, HERE << "request " << status() << ":\n" <<
43 (requestBuf.terminate(), requestBuf.content()));
44 icap_tio_start = current_time;
45 scheduleWrite(requestBuf);
46 }
47
48 void Adaptation::Icap::OptXact::makeRequest(MemBuf &buf)
49 {
50 const Adaptation::Service &s = service();
51 const String uri = s.cfg().uri;
52 buf.Printf("OPTIONS " SQUIDSTRINGPH " ICAP/1.0\r\n", SQUIDSTRINGPRINT(uri));
53 const String host = s.cfg().host;
54 buf.Printf("Host: " SQUIDSTRINGPH ":%d\r\n", SQUIDSTRINGPRINT(host), s.cfg().port);
55 if (TheConfig.allow206_enable)
56 buf.Printf("Allow: 206\r\n");
57 buf.append(ICAP::crlf, 2);
58
59 // XXX: HttpRequest cannot fully parse ICAP Request-Line
60 http_status reqStatus;
61 Must(icapRequest->parse(&buf, true, &reqStatus) > 0);
62 }
63
64 void Adaptation::Icap::OptXact::handleCommWrote(size_t size)
65 {
66 debugs(93, 9, HERE << "finished writing " << size <<
67 "-byte request " << status());
68 }
69
70 // comm module read a portion of the ICAP response for us
71 void Adaptation::Icap::OptXact::handleCommRead(size_t)
72 {
73 if (parseResponse()) {
74 Must(icapReply != NULL);
75 // We read everything if there is no response body. If there is a body,
76 // we cannot parse it because we do not support any opt-body-types, so
77 // we leave readAll false which forces connection closure.
78 readAll = !icapReply->header.getByNameListMember("Encapsulated",
79 "opt-body", ',').size();
80 debugs(93, 7, HERE << "readAll=" << readAll);
81 icap_tio_finish = current_time;
82 setOutcome(xoOpt);
83 sendAnswer(Answer::Forward(icapReply));
84 Must(done()); // there should be nothing else to do
85 return;
86 }
87
88 scheduleRead();
89 }
90
91 bool Adaptation::Icap::OptXact::parseResponse()
92 {
93 debugs(93, 5, HERE << "have " << readBuf.contentSize() << " bytes to parse" <<
94 status());
95 debugs(93, 5, HERE << "\n" << readBuf.content());
96
97 HttpReply::Pointer r(new HttpReply);
98 r->protoPrefix = "ICAP/"; // TODO: make an IcapReply class?
99
100 if (!parseHttpMsg(r)) // throws on errors
101 return false;
102
103 if (httpHeaderHasConnDir(&r->header, "close"))
104 reuseConnection = false;
105
106 icapReply = r;
107 return true;
108 }
109
110 void Adaptation::Icap::OptXact::swanSong()
111 {
112 Adaptation::Icap::Xaction::swanSong();
113 }
114
115 void Adaptation::Icap::OptXact::finalizeLogInfo()
116 {
117 // al.cache.caddr = 0;
118 al.icap.reqMethod = Adaptation::methodOptions;
119
120 if (icapReply && al.icap.bytesRead > icapReply->hdr_sz)
121 al.icap.bodyBytesRead = al.icap.bytesRead - icapReply->hdr_sz;
122
123 Adaptation::Icap::Xaction::finalizeLogInfo();
124 }
125
126 /* Adaptation::Icap::OptXactLauncher */
127
128 Adaptation::Icap::OptXactLauncher::OptXactLauncher(Adaptation::ServicePointer aService):
129 AsyncJob("Adaptation::Icap::OptXactLauncher"),
130 Adaptation::Icap::Launcher("Adaptation::Icap::OptXactLauncher", aService)
131 {
132 }
133
134 Adaptation::Icap::Xaction *Adaptation::Icap::OptXactLauncher::createXaction()
135 {
136 Adaptation::Icap::ServiceRep::Pointer s =
137 dynamic_cast<Adaptation::Icap::ServiceRep*>(theService.getRaw());
138 Must(s != NULL);
139 return new Adaptation::Icap::OptXact(s);
140 }