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