]>
Commit | Line | Data |
---|---|---|
774c051c | 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 | { | |
774c051c | 19 | } |
20 | ||
21 | ICAPOptXact::~ICAPOptXact() | |
22 | { | |
23 | Must(!options); // the caller must set to NULL | |
774c051c | 24 | } |
25 | ||
26 | void ICAPOptXact::start(ICAPServiceRep::Pointer &aService, Callback *aCb, void *aCbData) | |
27 | { | |
c99de607 | 28 | ICAPXaction_Enter(start); |
774c051c | 29 | service(aService); |
30 | ||
31 | Must(!cb && aCb && aCbData); | |
32 | cb = aCb; | |
33 | cbData = cbdataReference(aCbData); | |
34 | ||
35 | openConnection(); | |
c99de607 | 36 | |
37 | ICAPXaction_Exit(); | |
774c051c | 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 | ||
c99de607 | 53 | bool ICAPOptXact::doneAll() const |
54 | { | |
55 | return options && ICAPXaction::doneAll(); | |
56 | } | |
57 | ||
58 | ||
774c051c | 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 | ||
c99de607 | 73 | // get rid of options if we did not call the callback |
774c051c | 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 | { | |
c99de607 | 104 | debugs(93, 5, HERE << "have " << readBuf.contentSize() << " bytes to parse" << |
105 | status()); | |
106 | debugs(93, 5, HERE << "\n" << readBuf.content()); | |
107 | ||
774c051c | 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 | ||
b0ea5e03 | 120 | if (httpHeaderHasConnDir(&r->header, "close")) |
121 | reuseConnection = false; | |
122 | ||
774c051c | 123 | delete r; |
b0ea5e03 | 124 | |
774c051c | 125 | return true; |
126 | } |