]>
Commit | Line | Data |
---|---|---|
774c051c | 1 | #include "squid.h" |
2 | #include "http.h" | |
3 | #include "MsgPipe.h" | |
4 | #include "MsgPipeData.h" | |
5 | #include "MsgPipeSource.h" | |
6 | #include "MsgPipeSink.h" | |
7 | #include "HttpRequest.h" | |
8 | #include "HttpReply.h" | |
bab98cf3 | 9 | #include "ICAPClientRespmodPrecache.h" |
774c051c | 10 | #include "ICAPClient.h" |
11 | #include "ICAPServiceRep.h" | |
12 | ||
bab98cf3 | 13 | CBDATA_CLASS_INIT(ICAPClientRespmodPrecache); |
774c051c | 14 | |
bab98cf3 | 15 | ICAPClientRespmodPrecache::ICAPClientRespmodPrecache(ICAPServiceRep::Pointer aService): service(aService), httpState(NULL), virgin(NULL), adapted(NULL) |
774c051c | 16 | { |
bab98cf3 | 17 | debug(93,5)("ICAPClientRespmodPrecache constructed, this=%p\n", this); |
774c051c | 18 | } |
19 | ||
bab98cf3 | 20 | ICAPClientRespmodPrecache::~ICAPClientRespmodPrecache() |
774c051c | 21 | { |
22 | stop(notifyNone); | |
23 | cbdataReferenceDone(httpState); | |
bab98cf3 | 24 | debug(93,5)("ICAPClientRespmodPrecache destructed, this=%p\n", this); |
774c051c | 25 | |
26 | if (virgin != NULL) | |
27 | freeVirgin(); | |
28 | ||
29 | if (adapted != NULL) | |
30 | freeAdapted(); | |
31 | ||
32 | service = NULL; | |
33 | } | |
34 | ||
bab98cf3 | 35 | void ICAPClientRespmodPrecache::startRespMod(HttpStateData *anHttpState, HttpRequest *request, HttpReply *reply) |
774c051c | 36 | { |
37 | httpState = cbdataReference(anHttpState); | |
38 | ||
39 | virgin = new MsgPipe("virgin"); // this is the place to create a refcount ptr | |
774c051c | 40 | virgin->source = this; |
41 | virgin->data = new MsgPipeData; | |
42 | virgin->data->cause = requestLink(request); | |
43 | virgin->data->header = reply; | |
44 | virgin->data->body = new MemBuf; | |
45 | virgin->data->body->init(ICAP::MsgPipeBufSizeMin, ICAP::MsgPipeBufSizeMax); | |
46 | ||
47 | adapted = new MsgPipe("adapted"); | |
774c051c | 48 | adapted->sink = this; |
49 | #if ICAP_ANCHOR_LOOPBACK | |
50 | ||
51 | adapted->data = new MsgPipeData; | |
52 | adapted->data->cause = request; // should not hurt | |
53 | #else | |
54 | ||
55 | ICAPInitXaction(service, virgin, adapted); | |
56 | #endif | |
57 | ||
58 | virgin->sendSourceStart(); // we may have virgin data to provide | |
59 | adapted->sendSinkNeed(); // we want adapted response, eventially | |
60 | } | |
61 | ||
bab98cf3 | 62 | void ICAPClientRespmodPrecache::sendMoreData(StoreIOBuffer buf) |
774c051c | 63 | { |
bab98cf3 | 64 | debug(93,5)("ICAPClientRespmodPrecache::sendMoreData() called\n"); |
774c051c | 65 | //buf.dump(); |
66 | /* | |
67 | * The caller is responsible for not giving us more data | |
68 | * than will fit in body MemBuf. Caller should use | |
69 | * potentialSpaceSize() to find out how much we can hold. | |
70 | */ | |
774c051c | 71 | virgin->data->body->append(buf.data, buf.length); |
72 | virgin->sendSourceProgress(); | |
73 | } | |
74 | ||
75 | int | |
bab98cf3 | 76 | ICAPClientRespmodPrecache::potentialSpaceSize() |
774c051c | 77 | { |
78 | if (virgin == NULL) | |
79 | return 0; | |
80 | ||
774c051c | 81 | return (int) virgin->data->body->potentialSpaceSize(); |
82 | } | |
83 | ||
84 | // HttpStateData says we have the entire HTTP message | |
bab98cf3 | 85 | void ICAPClientRespmodPrecache::doneSending() |
774c051c | 86 | { |
bab98cf3 | 87 | debug(93,5)("ICAPClientRespmodPrecache::doneSending() called\n"); |
774c051c | 88 | |
89 | #if ICAP_ANCHOR_LOOPBACK | |
90 | /* simple assignments are not the right way to do this */ | |
91 | adapted->data->header = virgin->data->header; | |
92 | adapted->data->body = virgin->data->body; | |
93 | noteSourceFinish(adapted); | |
94 | return; | |
95 | #else | |
96 | ||
774c051c | 97 | virgin->sendSourceFinish(); |
98 | #endif | |
99 | } | |
100 | ||
101 | // HttpStateData tells us to abort | |
bab98cf3 | 102 | void ICAPClientRespmodPrecache::ownerAbort() |
774c051c | 103 | { |
bab98cf3 | 104 | debug(93,5)("ICAPClientRespmodPrecache::ownerAbort() called\n"); |
774c051c | 105 | stop(notifyIcap); |
106 | } | |
107 | ||
108 | // ICAP client needs more virgin response data | |
bab98cf3 | 109 | void ICAPClientRespmodPrecache::noteSinkNeed(MsgPipe *p) |
774c051c | 110 | { |
bab98cf3 | 111 | debug(93,5)("ICAPClientRespmodPrecache::noteSinkNeed() called\n"); |
774c051c | 112 | |
774c051c | 113 | if (virgin->data->body->potentialSpaceSize()) |
114 | httpState->icapSpaceAvailable(); | |
115 | } | |
116 | ||
117 | // ICAP client aborting | |
bab98cf3 | 118 | void ICAPClientRespmodPrecache::noteSinkAbort(MsgPipe *p) |
774c051c | 119 | { |
bab98cf3 | 120 | debug(93,5)("ICAPClientRespmodPrecache::noteSinkAbort() called\n"); |
774c051c | 121 | stop(notifyOwner); |
122 | } | |
123 | ||
124 | // ICAP client starts sending adapted response | |
125 | // ICAP client has received new HTTP headers (if any) at this point | |
bab98cf3 | 126 | void ICAPClientRespmodPrecache::noteSourceStart(MsgPipe *p) |
774c051c | 127 | { |
bab98cf3 | 128 | debug(93,5)("ICAPClientRespmodPrecache::noteSourceStart() called\n"); |
774c051c | 129 | |
130 | HttpReply *reply = dynamic_cast<HttpReply*>(adapted->data->header); | |
b559db5d | 131 | /* |
132 | * The ICAP reply MUST have a new HTTP reply header, or else | |
133 | * it is an invalid ICAP message. Invalid ICAP messages should | |
134 | * be handled prior to this point. | |
135 | */ | |
774c051c | 136 | assert(reply); // check that ICAP xaction created the right object |
137 | httpState->takeAdaptedHeaders(reply); | |
138 | ||
139 | assert(reply == adapted->data->header); | |
140 | adapted->data->header = NULL; | |
141 | ||
142 | noteSourceProgress(p); | |
143 | } | |
144 | ||
145 | // ICAP client sends more data | |
bab98cf3 | 146 | void ICAPClientRespmodPrecache::noteSourceProgress(MsgPipe *p) |
774c051c | 147 | { |
bab98cf3 | 148 | debug(93,5)("ICAPClientRespmodPrecache::noteSourceProgress() called\n"); |
774c051c | 149 | //tell HttpStateData to store a fresh portion of the adapted response |
150 | ||
774c051c | 151 | if (p->data->body->hasContent()) { |
152 | httpState->takeAdaptedBody(p->data->body); | |
153 | } | |
154 | } | |
155 | ||
156 | // ICAP client is done sending adapted response | |
bab98cf3 | 157 | void ICAPClientRespmodPrecache::noteSourceFinish(MsgPipe *p) |
774c051c | 158 | { |
bab98cf3 | 159 | debug(93,5)("ICAPClientRespmodPrecache::noteSourceFinish() called\n"); |
774c051c | 160 | //tell HttpStateData that we expect no more response data |
774c051c | 161 | httpState->doneAdapting(); |
162 | stop(notifyNone); | |
163 | } | |
164 | ||
165 | // ICAP client is aborting | |
bab98cf3 | 166 | void ICAPClientRespmodPrecache::noteSourceAbort(MsgPipe *p) |
774c051c | 167 | { |
bab98cf3 | 168 | debug(93,5)("ICAPClientRespmodPrecache::noteSourceAbort() called\n"); |
774c051c | 169 | stop(notifyOwner); |
170 | } | |
171 | ||
172 | // internal cleanup | |
bab98cf3 | 173 | void ICAPClientRespmodPrecache::stop(Notify notify) |
774c051c | 174 | { |
175 | if (virgin != NULL) { | |
774c051c | 176 | if (notify == notifyIcap) |
177 | virgin->sendSourceAbort(); | |
178 | else | |
179 | virgin->source = NULL; | |
180 | ||
181 | freeVirgin(); | |
182 | } | |
183 | ||
184 | if (adapted != NULL) { | |
774c051c | 185 | if (notify == notifyIcap) |
186 | adapted->sendSinkAbort(); | |
187 | else | |
188 | adapted->sink = NULL; | |
189 | ||
190 | freeAdapted(); | |
191 | } | |
192 | ||
193 | if (httpState) { | |
194 | if (notify == notifyOwner) | |
195 | // tell HttpStateData that we are aborting prematurely | |
196 | httpState->abortAdapting(); | |
197 | ||
198 | cbdataReferenceDone(httpState); | |
199 | ||
200 | // httpState is now NULL, will not call it any more | |
201 | } | |
202 | } | |
203 | ||
bab98cf3 | 204 | void ICAPClientRespmodPrecache::freeVirgin() |
774c051c | 205 | { |
206 | requestUnlink(virgin->data->cause); | |
207 | virgin->data->cause = NULL; | |
208 | virgin->data->header = NULL; | |
774c051c | 209 | virgin = NULL; // refcounted |
210 | } | |
211 | ||
bab98cf3 | 212 | void ICAPClientRespmodPrecache::freeAdapted() |
774c051c | 213 | { |
214 | /* | |
215 | * Note on adapted->data->header. ICAPXaction-side created it | |
216 | * but gave control of it to us. Normally we give it to | |
217 | * HttpStateData::takeAdaptedHeader. If not, we have to | |
218 | * make sure it gets deleted; | |
219 | */ | |
220 | ||
221 | if (adapted->data->header != NULL) { | |
222 | debug(93,3)("hey, adapted->data->header is still set!\n"); | |
223 | delete adapted->data->header; | |
224 | adapted->data->header = NULL; | |
225 | } | |
226 | ||
774c051c | 227 | adapted = NULL; // refcounted |
228 | } |