]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ICAP/ICAPOptXact.cc
- Many ICAP fixes from Alex Rousskov accumulated on the
[thirdparty/squid.git] / src / ICAP / ICAPOptXact.cc
1 /*
2 * DEBUG: section 93 ICAP (RFC 3507) Client
3 */
4
5 #include "squid.h"
6 #include "comm.h"
7 #include "HttpReply.h"
8
9 #include "ICAPOptXact.h"
10 #include "ICAPOptions.h"
11 #include "TextException.h"
12
13 CBDATA_CLASS_INIT(ICAPOptXact);
14
15 ICAPOptXact::ICAPOptXact(): ICAPXaction("ICAPOptXact"), options(NULL),
16 cb(NULL), cbData(NULL)
17
18 {
19 }
20
21 ICAPOptXact::~ICAPOptXact()
22 {
23 Must(!options); // the caller must set to NULL
24 }
25
26 void ICAPOptXact::start(ICAPServiceRep::Pointer &aService, Callback *aCb, void *aCbData)
27 {
28 ICAPXaction_Enter(start);
29 service(aService);
30
31 Must(!cb && aCb && aCbData);
32 cb = aCb;
33 cbData = cbdataReference(aCbData);
34
35 openConnection();
36
37 ICAPXaction_Exit();
38 }
39
40 void ICAPOptXact::handleCommConnected()
41 {
42 scheduleRead();
43
44 MemBuf requestBuf;
45 requestBuf.init();
46 makeRequest(requestBuf);
47 debugs(93, 9, "ICAPOptXact request " << status() << ":\n" <<
48 (requestBuf.terminate(), requestBuf.content()));
49
50 scheduleWrite(requestBuf);
51 }
52
53 bool ICAPOptXact::doneAll() const
54 {
55 return options && ICAPXaction::doneAll();
56 }
57
58
59 void ICAPOptXact::doStop()
60 {
61 ICAPXaction::doStop();
62
63 if (Callback *call = cb) {
64 cb = NULL;
65 void *data = NULL;
66
67 if (cbdataReferenceValidDone(cbData, &data)) {
68 (*call)(this, data); // will delete us
69 return;
70 }
71 }
72
73 // get rid of options if we did not call the callback
74 delete options;
75
76 options = NULL;
77 }
78
79 void ICAPOptXact::makeRequest(MemBuf &buf)
80 {
81 const ICAPServiceRep &s = service();
82 buf.Printf("OPTIONS %s ICAP/1.0\r\n", s.uri.buf());
83 buf.Printf("Host: %s:%d\r\n", s.host.buf(), s.port);
84 buf.append(ICAP::crlf, 2);
85 }
86
87 void ICAPOptXact::handleCommWrote(size_t size)
88 {
89 debugs(93, 9, "ICAPOptXact finished writing " << size <<
90 "-byte request " << status());
91 }
92
93 // comm module read a portion of the ICAP response for us
94 void ICAPOptXact::handleCommRead(size_t)
95 {
96 if (parseResponse())
97 Must(done()); // there should be nothing else to do
98 else
99 scheduleRead();
100 }
101
102 bool ICAPOptXact::parseResponse()
103 {
104 debugs(93, 5, HERE << "have " << readBuf.contentSize() << " bytes to parse" <<
105 status());
106 debugs(93, 5, HERE << "\n" << readBuf.content());
107
108 HttpReply *r = new HttpReply;
109 r->protoPrefix = "ICAP/"; // TODO: make an IcapReply class?
110
111 if (!parseHttpMsg(r)) {
112 delete r;
113 return false;
114 }
115
116 options = new ICAPOptions;
117
118 options->configure(r);
119
120 if (httpHeaderHasConnDir(&r->header, "close"))
121 reuseConnection = false;
122
123 delete r;
124
125 return true;
126 }