]>
Commit | Line | Data |
---|---|---|
26cc52cb | 1 | /* |
77b1029d | 2 | * Copyright (C) 1996-2020 The Squid Software Foundation and contributors |
bbc27441 AJ |
3 | * |
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. | |
26cc52cb AR |
7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 93 ICAP (RFC 3507) Client */ |
10 | ||
582c2af2 | 11 | #include "squid.h" |
1adcebc3 | 12 | #include "adaptation/Answer.h" |
83c51da9 | 13 | #include "adaptation/icap/Config.h" |
582c2af2 FC |
14 | #include "adaptation/icap/Options.h" |
15 | #include "adaptation/icap/OptXact.h" | |
3d93a84d | 16 | #include "base/TextException.h" |
582c2af2 | 17 | #include "comm.h" |
a5bac1d2 | 18 | #include "HttpHeaderTools.h" |
582c2af2 | 19 | #include "HttpReply.h" |
3ff65596 | 20 | #include "HttpRequest.h" |
582c2af2 | 21 | #include "SquidTime.h" |
26cc52cb AR |
22 | |
23 | CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, OptXact); | |
24 | CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, OptXactLauncher); | |
25 | ||
4299f876 | 26 | Adaptation::Icap::OptXact::OptXact(Adaptation::Icap::ServiceRep::Pointer &aService): |
f53969cc SM |
27 | AsyncJob("Adaptation::Icap::OptXact"), |
28 | Adaptation::Icap::Xaction("Adaptation::Icap::OptXact", aService), | |
29 | readAll(false) | |
26cc52cb AR |
30 | { |
31 | } | |
32 | ||
33 | void Adaptation::Icap::OptXact::start() | |
34 | { | |
35 | Adaptation::Icap::Xaction::start(); | |
36 | ||
37 | openConnection(); | |
38 | } | |
39 | ||
40 | void Adaptation::Icap::OptXact::handleCommConnected() | |
41 | { | |
42 | scheduleRead(); | |
43 | ||
44 | MemBuf requestBuf; | |
45 | requestBuf.init(); | |
46 | makeRequest(requestBuf); | |
192378eb | 47 | debugs(93, 9, HERE << "request " << status() << ":\n" << |
26cc52cb | 48 | (requestBuf.terminate(), requestBuf.content())); |
3ff65596 | 49 | icap_tio_start = current_time; |
26cc52cb AR |
50 | scheduleWrite(requestBuf); |
51 | } | |
52 | ||
53 | void Adaptation::Icap::OptXact::makeRequest(MemBuf &buf) | |
54 | { | |
55 | const Adaptation::Service &s = service(); | |
56 | const String uri = s.cfg().uri; | |
4391cd15 | 57 | buf.appendf("OPTIONS " SQUIDSTRINGPH " ICAP/1.0\r\n", SQUIDSTRINGPRINT(uri)); |
26cc52cb | 58 | const String host = s.cfg().host; |
4391cd15 | 59 | buf.appendf("Host: " SQUIDSTRINGPH ":%d\r\n", SQUIDSTRINGPRINT(host), s.cfg().port); |
77f6d1d2 NH |
60 | |
61 | if (!TheConfig.reuse_connections) | |
4391cd15 | 62 | buf.append("Connection: close\r\n", 19); |
77f6d1d2 | 63 | |
69c698a3 | 64 | buf.append("Allow: ", 7); |
83c51da9 | 65 | if (TheConfig.allow206_enable) |
69c698a3 EB |
66 | buf.append("206, ", 5); |
67 | buf.append("trailers\r\n", 10); | |
26cc52cb | 68 | buf.append(ICAP::crlf, 2); |
3ff65596 AR |
69 | |
70 | // XXX: HttpRequest cannot fully parse ICAP Request-Line | |
955394ce | 71 | Http::StatusCode reqStatus; |
63df1d28 | 72 | buf.terminate(); // Http::Message::parse requires terminated buffer |
84ae6223 | 73 | Must(icapRequest->parse(buf.content(), buf.contentSize(), true, &reqStatus) > 0); |
26cc52cb AR |
74 | } |
75 | ||
76 | void Adaptation::Icap::OptXact::handleCommWrote(size_t size) | |
77 | { | |
192378eb | 78 | debugs(93, 9, HERE << "finished writing " << size << |
26cc52cb AR |
79 | "-byte request " << status()); |
80 | } | |
81 | ||
82 | // comm module read a portion of the ICAP response for us | |
83 | void Adaptation::Icap::OptXact::handleCommRead(size_t) | |
84 | { | |
c7d51c86 | 85 | if (parseResponse()) { |
0a1ac29e AR |
86 | Must(icapReply != NULL); |
87 | // We read everything if there is no response body. If there is a body, | |
88 | // we cannot parse it because we do not support any opt-body-types, so | |
89 | // we leave readAll false which forces connection closure. | |
36c774f7 EB |
90 | readAll = icapReply->header.getByNameListMember("Encapsulated", |
91 | "opt-body", ',').isEmpty(); | |
0a1ac29e | 92 | debugs(93, 7, HERE << "readAll=" << readAll); |
3ff65596 AR |
93 | icap_tio_finish = current_time; |
94 | setOutcome(xoOpt); | |
b248c2a3 | 95 | sendAnswer(Answer::Forward(icapReply.getRaw())); |
26cc52cb AR |
96 | Must(done()); // there should be nothing else to do |
97 | return; | |
98 | } | |
99 | ||
100 | scheduleRead(); | |
101 | } | |
102 | ||
c7d51c86 | 103 | bool Adaptation::Icap::OptXact::parseResponse() |
26cc52cb | 104 | { |
84ae6223 AJ |
105 | debugs(93, 5, "have " << readBuf.length() << " bytes to parse" << status()); |
106 | debugs(93, DBG_DATA, "\n" << readBuf); | |
26cc52cb | 107 | |
c7d51c86 | 108 | HttpReply::Pointer r(new HttpReply); |
26cc52cb AR |
109 | r->protoPrefix = "ICAP/"; // TODO: make an IcapReply class? |
110 | ||
b248c2a3 | 111 | if (!parseHttpMsg(r.getRaw())) // throws on errors |
c7d51c86 | 112 | return false; |
26cc52cb | 113 | |
d5f18517 AJ |
114 | static SBuf close("close", 5); |
115 | if (httpHeaderHasConnDir(&r->header, close)) | |
26cc52cb AR |
116 | reuseConnection = false; |
117 | ||
c7d51c86 AR |
118 | icapReply = r; |
119 | return true; | |
26cc52cb AR |
120 | } |
121 | ||
3ff65596 AR |
122 | void Adaptation::Icap::OptXact::swanSong() |
123 | { | |
124 | Adaptation::Icap::Xaction::swanSong(); | |
125 | } | |
126 | ||
127 | void Adaptation::Icap::OptXact::finalizeLogInfo() | |
128 | { | |
129 | // al.cache.caddr = 0; | |
130 | al.icap.reqMethod = Adaptation::methodOptions; | |
bae917ac | 131 | |
b248c2a3 | 132 | if (icapReply != NULL && al.icap.bytesRead > icapReply->hdr_sz) |
bae917ac CT |
133 | al.icap.bodyBytesRead = al.icap.bytesRead - icapReply->hdr_sz; |
134 | ||
3ff65596 AR |
135 | Adaptation::Icap::Xaction::finalizeLogInfo(); |
136 | } | |
137 | ||
26cc52cb AR |
138 | /* Adaptation::Icap::OptXactLauncher */ |
139 | ||
4299f876 | 140 | Adaptation::Icap::OptXactLauncher::OptXactLauncher(Adaptation::ServicePointer aService): |
f53969cc SM |
141 | AsyncJob("Adaptation::Icap::OptXactLauncher"), |
142 | Adaptation::Icap::Launcher("Adaptation::Icap::OptXactLauncher", aService) | |
26cc52cb AR |
143 | { |
144 | } | |
145 | ||
146 | Adaptation::Icap::Xaction *Adaptation::Icap::OptXactLauncher::createXaction() | |
147 | { | |
148 | Adaptation::Icap::ServiceRep::Pointer s = | |
149 | dynamic_cast<Adaptation::Icap::ServiceRep*>(theService.getRaw()); | |
150 | Must(s != NULL); | |
4299f876 | 151 | return new Adaptation::Icap::OptXact(s); |
26cc52cb | 152 | } |
f53969cc | 153 |