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