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