]>
Commit | Line | Data |
---|---|---|
b510f3a1 AJ |
1 | /* |
2 | * DEBUG: section 93 eCAP Interface | |
3 | */ | |
fdc96a39 | 4 | #include "squid.h" |
4d0854d4 AR |
5 | #include <libecap/common/area.h> |
6 | #include <libecap/common/delay.h> | |
22fff3bf AR |
7 | #include <libecap/common/named_values.h> |
8 | #include <libecap/common/names.h> | |
fdc96a39 | 9 | #include <libecap/adapter/xaction.h> |
fdc96a39 AR |
10 | #include "HttpRequest.h" |
11 | #include "HttpReply.h" | |
3ff65596 | 12 | #include "SquidTime.h" |
1f3c65fc | 13 | #include "adaptation/ecap/XactionRep.h" |
22fff3bf | 14 | #include "adaptation/ecap/Config.h" |
3af10ac0 | 15 | #include "adaptation/Initiator.h" |
3d93a84d | 16 | #include "base/TextException.h" |
fdc96a39 | 17 | |
574b508c | 18 | CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Ecap::XactionRep, XactionRep); |
fdc96a39 AR |
19 | |
20 | ||
4299f876 | 21 | Adaptation::Ecap::XactionRep::XactionRep( |
4cb2536f A |
22 | HttpMsg *virginHeader, HttpRequest *virginCause, |
23 | const Adaptation::ServicePointer &aService): | |
574b508c | 24 | AsyncJob("Adaptation::Ecap::XactionRep"), |
4299f876 | 25 | Adaptation::Initiate("Adaptation::Ecap::XactionRep"), |
a22e6cd3 | 26 | theService(aService), |
26ac0430 | 27 | theVirginRep(virginHeader), theCauseRep(NULL), |
e1e90d26 | 28 | makingVb(opUndecided), proxyingAb(opUndecided), |
3ff65596 | 29 | adaptHistoryId(-1), |
e1e90d26 | 30 | vbProductionFinished(false), |
7477a343 | 31 | abProductionFinished(false), abProductionAtEnd(false) |
fdc96a39 | 32 | { |
027320b4 | 33 | if (virginCause) |
4d0854d4 | 34 | theCauseRep = new MessageRep(virginCause); |
fdc96a39 AR |
35 | } |
36 | ||
574b508c | 37 | Adaptation::Ecap::XactionRep::~XactionRep() |
fdc96a39 AR |
38 | { |
39 | assert(!theMaster); | |
027320b4 | 40 | delete theCauseRep; |
4d0854d4 | 41 | theAnswerRep.reset(); |
fdc96a39 AR |
42 | } |
43 | ||
44 | void | |
574b508c | 45 | Adaptation::Ecap::XactionRep::master(const AdapterXaction &x) |
fdc96a39 AR |
46 | { |
47 | Must(!theMaster); | |
48 | Must(x != NULL); | |
49 | theMaster = x; | |
50 | } | |
51 | ||
a22e6cd3 AR |
52 | Adaptation::Service & |
53 | Adaptation::Ecap::XactionRep::service() | |
54 | { | |
55 | Must(theService != NULL); | |
56 | return *theService; | |
57 | } | |
58 | ||
22fff3bf AR |
59 | const libecap::Area |
60 | Adaptation::Ecap::XactionRep::option(const libecap::Name &name) const | |
61 | { | |
62 | if (name == libecap::metaClientIp) | |
63 | return clientIpValue(); | |
64 | if (name == libecap::metaUserName) | |
65 | return usernameValue(); | |
66 | // TODO: metaServerIp, metaAuthenticatedUser, metaAuthenticatedGroups, and | |
67 | // Adaptation::Config::masterx_shared_name | |
68 | return libecap::Area(); | |
69 | } | |
70 | ||
71 | void | |
72 | Adaptation::Ecap::XactionRep::visitEachOption(libecap::NamedValueVisitor &visitor) const | |
73 | { | |
74 | if (const libecap::Area value = clientIpValue()) | |
75 | visitor.visit(libecap::metaClientIp, value); | |
76 | if (const libecap::Area value = usernameValue()) | |
77 | visitor.visit(libecap::metaUserName, value); | |
78 | // TODO: metaServerIp, metaAuthenticatedUser, metaAuthenticatedGroups, and | |
79 | // Adaptation::Config::masterx_shared_name | |
80 | } | |
81 | ||
82 | const libecap::Area | |
83 | Adaptation::Ecap::XactionRep::clientIpValue() const | |
84 | { | |
85 | const HttpRequest *request = dynamic_cast<const HttpRequest*>(theCauseRep ? | |
86 | theCauseRep->raw().header : theVirginRep.raw().header); | |
87 | Must(request); | |
88 | // TODO: move this logic into HttpRequest::clientIp(bool) and | |
89 | // HttpRequest::clientIpString(bool) and reuse everywhere | |
90 | if (TheConfig.send_client_ip && request) { | |
91 | Ip::Address client_addr; | |
92 | #if FOLLOW_X_FORWARDED_FOR | |
93 | if (TheConfig.use_indirect_client) { | |
94 | client_addr = request->indirect_client_addr; | |
95 | } else | |
96 | #endif | |
97 | client_addr = request->client_addr; | |
98 | if (!client_addr.IsAnyAddr() && !client_addr.IsNoAddr()) { | |
99 | char ntoabuf[MAX_IPSTRLEN] = ""; | |
100 | client_addr.NtoA(ntoabuf,MAX_IPSTRLEN); | |
101 | return libecap::Area::FromTempBuffer(ntoabuf, strlen(ntoabuf)); | |
102 | } | |
103 | } | |
104 | return libecap::Area(); | |
105 | } | |
106 | ||
107 | const libecap::Area | |
108 | Adaptation::Ecap::XactionRep::usernameValue() const | |
109 | { | |
110 | const HttpRequest *request = dynamic_cast<const HttpRequest*>(theCauseRep ? | |
111 | theCauseRep->raw().header : theVirginRep.raw().header); | |
112 | Must(request); | |
113 | if (request->auth_user_request != NULL) { | |
114 | if (char const *name = request->auth_user_request->username()) | |
115 | return libecap::Area::FromTempBuffer(name, strlen(name)); | |
116 | } | |
117 | return libecap::Area(); | |
118 | } | |
119 | ||
fdc96a39 | 120 | void |
574b508c | 121 | Adaptation::Ecap::XactionRep::start() |
fdc96a39 AR |
122 | { |
123 | Must(theMaster); | |
4d0854d4 | 124 | |
e1e90d26 AR |
125 | if (!theVirginRep.raw().body_pipe) |
126 | makingVb = opNever; // there is nothing to deliver | |
4d0854d4 | 127 | |
3ff65596 | 128 | const HttpRequest *request = dynamic_cast<const HttpRequest*> (theCauseRep ? |
e1381638 | 129 | theCauseRep->raw().header : theVirginRep.raw().header); |
3ff65596 | 130 | Must(request); |
a22e6cd3 | 131 | Adaptation::History::Pointer ah = request->adaptLogHistory(); |
e1381638 | 132 | if (ah != NULL) { |
3ff65596 AR |
133 | // retrying=false because ecap never retries transactions |
134 | adaptHistoryId = ah->recordXactStart(service().cfg().key, current_time, false); | |
135 | } | |
136 | ||
fdc96a39 AR |
137 | theMaster->start(); |
138 | } | |
139 | ||
140 | void | |
574b508c | 141 | Adaptation::Ecap::XactionRep::swanSong() |
fdc96a39 | 142 | { |
506a0530 | 143 | // clear body_pipes, if any |
ea76d91e | 144 | // this code does not maintain proxying* and canAccessVb states; should it? |
506a0530 AR |
145 | |
146 | if (theAnswerRep != NULL) { | |
f1a768b2 AR |
147 | BodyPipe::Pointer body_pipe = answer().body_pipe; |
148 | if (body_pipe != NULL) { | |
149 | Must(body_pipe->stillProducing(this)); | |
150 | stopProducingFor(body_pipe, false); | |
151 | } | |
152 | } | |
506a0530 | 153 | |
e1e90d26 AR |
154 | BodyPipe::Pointer &body_pipe = theVirginRep.raw().body_pipe; |
155 | if (body_pipe != NULL && body_pipe->stillConsuming(this)) | |
156 | stopConsumingFrom(body_pipe); | |
506a0530 | 157 | |
fdc96a39 | 158 | terminateMaster(); |
3ff65596 AR |
159 | |
160 | const HttpRequest *request = dynamic_cast<const HttpRequest*>(theCauseRep ? | |
e1381638 | 161 | theCauseRep->raw().header : theVirginRep.raw().header); |
3ff65596 | 162 | Must(request); |
a22e6cd3 | 163 | Adaptation::History::Pointer ah = request->adaptLogHistory(); |
3ff65596 AR |
164 | if (ah != NULL && adaptHistoryId >= 0) |
165 | ah->recordXactFinish(adaptHistoryId); | |
166 | ||
fdc96a39 AR |
167 | Adaptation::Initiate::swanSong(); |
168 | } | |
169 | ||
fdc96a39 | 170 | libecap::Message & |
574b508c | 171 | Adaptation::Ecap::XactionRep::virgin() |
fdc96a39 | 172 | { |
7b67e5b6 | 173 | return theVirginRep; |
fdc96a39 AR |
174 | } |
175 | ||
4d0854d4 | 176 | const libecap::Message & |
574b508c | 177 | Adaptation::Ecap::XactionRep::cause() |
fdc96a39 | 178 | { |
4d0854d4 AR |
179 | Must(theCauseRep != NULL); |
180 | return *theCauseRep; | |
fdc96a39 AR |
181 | } |
182 | ||
4d0854d4 | 183 | libecap::Message & |
574b508c | 184 | Adaptation::Ecap::XactionRep::adapted() |
fdc96a39 | 185 | { |
4d0854d4 AR |
186 | Must(theAnswerRep != NULL); |
187 | return *theAnswerRep; | |
188 | } | |
189 | ||
190 | Adaptation::Message & | |
574b508c | 191 | Adaptation::Ecap::XactionRep::answer() |
4d0854d4 | 192 | { |
f1a768b2 AR |
193 | MessageRep *rep = dynamic_cast<MessageRep*>(theAnswerRep.get()); |
194 | Must(rep); | |
4d0854d4 AR |
195 | return rep->raw(); |
196 | } | |
197 | ||
ea76d91e | 198 | void |
574b508c | 199 | Adaptation::Ecap::XactionRep::terminateMaster() |
4d0854d4 AR |
200 | { |
201 | if (theMaster) { | |
ea76d91e AR |
202 | AdapterXaction x = theMaster; |
203 | theMaster.reset(); | |
204 | x->stop(); | |
f1a768b2 | 205 | } |
4d0854d4 AR |
206 | } |
207 | ||
4d0854d4 | 208 | bool |
574b508c | 209 | Adaptation::Ecap::XactionRep::doneAll() const |
4d0854d4 | 210 | { |
e1e90d26 | 211 | return makingVb >= opComplete && proxyingAb >= opComplete && |
26ac0430 | 212 | Adaptation::Initiate::doneAll(); |
4d0854d4 AR |
213 | } |
214 | ||
e1e90d26 | 215 | // stops receiving virgin and enables auto-consumption, dropping any vb bytes |
4d0854d4 | 216 | void |
e1e90d26 | 217 | Adaptation::Ecap::XactionRep::sinkVb(const char *reason) |
4d0854d4 | 218 | { |
e1e90d26 | 219 | debugs(93,4, HERE << "sink for " << reason << "; status:" << status()); |
4d0854d4 | 220 | |
e1e90d26 AR |
221 | // we reset raw().body_pipe when we are done, so use this one for checking |
222 | const BodyPipePointer &permPipe = theVirginRep.raw().header->body_pipe; | |
223 | if (permPipe != NULL) | |
224 | permPipe->enableAutoConsumption(); | |
3af10ac0 | 225 | |
e1e90d26 AR |
226 | forgetVb(reason); |
227 | } | |
228 | ||
229 | // stops receiving virgin but preserves it for others to use | |
230 | void | |
231 | Adaptation::Ecap::XactionRep::preserveVb(const char *reason) | |
232 | { | |
233 | debugs(93,4, HERE << "preserve for " << reason << "; status:" << status()); | |
234 | ||
235 | // we reset raw().body_pipe when we are done, so use this one for checking | |
236 | const BodyPipePointer &permPipe = theVirginRep.raw().header->body_pipe; | |
237 | if (permPipe != NULL) { | |
238 | // if libecap consumed, we cannot preserve | |
239 | Must(!permPipe->consumedSize()); | |
3af10ac0 AR |
240 | } |
241 | ||
e1e90d26 AR |
242 | forgetVb(reason); |
243 | } | |
244 | ||
245 | // disassociates us from vb; the last step of sinking or preserving vb | |
246 | void | |
247 | Adaptation::Ecap::XactionRep::forgetVb(const char *reason) | |
248 | { | |
249 | debugs(93,9, HERE << "forget vb " << reason << "; status:" << status()); | |
ea76d91e | 250 | |
e1e90d26 AR |
251 | BodyPipePointer &p = theVirginRep.raw().body_pipe; |
252 | if (p != NULL && p->stillConsuming(this)) | |
253 | stopConsumingFrom(p); | |
254 | ||
255 | if (makingVb == opUndecided) | |
256 | makingVb = opNever; | |
257 | else if (makingVb == opOn) | |
258 | makingVb = opComplete; | |
fdc96a39 AR |
259 | } |
260 | ||
26ac0430 | 261 | void |
574b508c | 262 | Adaptation::Ecap::XactionRep::useVirgin() |
fdc96a39 | 263 | { |
4d0854d4 | 264 | debugs(93,3, HERE << status()); |
ea76d91e AR |
265 | Must(proxyingAb == opUndecided); |
266 | proxyingAb = opNever; | |
4d0854d4 | 267 | |
e1e90d26 | 268 | preserveVb("useVirgin"); |
2874d9e3 AR |
269 | |
270 | HttpMsg *clone = theVirginRep.raw().header->clone(); | |
271 | // check that clone() copies the pipe so that we do not have to | |
e1e90d26 | 272 | Must(!theVirginRep.raw().header->body_pipe == !clone->body_pipe); |
ea76d91e | 273 | |
3af10ac0 | 274 | sendAnswer(Answer::Forward(clone)); |
4d0854d4 | 275 | Must(done()); |
fdc96a39 AR |
276 | } |
277 | ||
26ac0430 | 278 | void |
574b508c | 279 | Adaptation::Ecap::XactionRep::useAdapted(const libecap::shared_ptr<libecap::Message> &m) |
fdc96a39 | 280 | { |
4d0854d4 | 281 | debugs(93,3, HERE << status()); |
ea76d91e | 282 | Must(m); |
4d0854d4 | 283 | theAnswerRep = m; |
ea76d91e AR |
284 | Must(proxyingAb == opUndecided); |
285 | ||
f1a768b2 | 286 | HttpMsg *msg = answer().header; |
ea76d91e AR |
287 | if (!theAnswerRep->body()) { // final, bodyless answer |
288 | proxyingAb = opNever; | |
3af10ac0 | 289 | sendAnswer(Answer::Forward(msg)); |
f1a768b2 | 290 | } else { // got answer headers but need to handle body |
ea76d91e | 291 | proxyingAb = opOn; |
f1a768b2 | 292 | Must(!msg->body_pipe); // only host can set body pipes |
ea76d91e | 293 | MessageRep *rep = dynamic_cast<MessageRep*>(theAnswerRep.get()); |
f1a768b2 AR |
294 | Must(rep); |
295 | rep->tieBody(this); // sets us as a producer | |
296 | Must(msg->body_pipe != NULL); // check tieBody | |
ea76d91e | 297 | |
3af10ac0 | 298 | sendAnswer(Answer::Forward(msg)); |
ea76d91e | 299 | |
4d0854d4 | 300 | debugs(93,4, HERE << "adapter will produce body" << status()); |
8679e6c2 | 301 | theMaster->abMake(); // libecap will produce |
4d0854d4 | 302 | } |
fdc96a39 AR |
303 | } |
304 | ||
3af10ac0 AR |
305 | void |
306 | Adaptation::Ecap::XactionRep::blockVirgin() | |
307 | { | |
308 | debugs(93,3, HERE << status()); | |
309 | Must(proxyingAb == opUndecided); | |
310 | proxyingAb = opNever; | |
311 | ||
e1e90d26 | 312 | sinkVb("blockVirgin"); |
3af10ac0 AR |
313 | |
314 | sendAnswer(Answer::Block(service().cfg().key)); | |
315 | Must(done()); | |
316 | } | |
317 | ||
4d0854d4 | 318 | void |
574b508c | 319 | Adaptation::Ecap::XactionRep::vbDiscard() |
fdc96a39 | 320 | { |
e1e90d26 | 321 | Must(makingVb == opUndecided); |
8679e6c2 | 322 | // if adapter does not need vb, we do not need to send it |
e1e90d26 AR |
323 | sinkVb("vbDiscard"); |
324 | Must(makingVb == opNever); | |
fdc96a39 AR |
325 | } |
326 | ||
4d0854d4 | 327 | void |
574b508c | 328 | Adaptation::Ecap::XactionRep::vbMake() |
fdc96a39 | 329 | { |
e1e90d26 | 330 | Must(makingVb == opUndecided); |
ea76d91e AR |
331 | BodyPipePointer &p = theVirginRep.raw().body_pipe; |
332 | Must(p != NULL); | |
e1e90d26 AR |
333 | Must(p->setConsumerIfNotLate(this)); // to deliver vb, we must receive vb |
334 | makingVb = opOn; | |
fdc96a39 AR |
335 | } |
336 | ||
4d0854d4 | 337 | void |
574b508c | 338 | Adaptation::Ecap::XactionRep::vbStopMaking() |
fdc96a39 | 339 | { |
e1e90d26 | 340 | Must(makingVb == opOn); |
ea76d91e | 341 | // if adapter does not need vb, we do not need to receive it |
e1e90d26 AR |
342 | sinkVb("vbStopMaking"); |
343 | Must(makingVb == opComplete); | |
4d0854d4 AR |
344 | } |
345 | ||
346 | void | |
574b508c | 347 | Adaptation::Ecap::XactionRep::vbMakeMore() |
4d0854d4 | 348 | { |
e1e90d26 | 349 | Must(makingVb == opOn); // cannot make more if done proxying |
ea76d91e | 350 | // we cannot guarantee more vb, but we can check that there is a chance |
e1e90d26 AR |
351 | const BodyPipePointer &p = theVirginRep.raw().body_pipe; |
352 | Must(p != NULL && p->stillConsuming(this)); // we are plugged in | |
353 | Must(!p->productionEnded() && p->mayNeedMoreData()); // and may get more | |
4d0854d4 AR |
354 | } |
355 | ||
8679e6c2 | 356 | libecap::Area |
574b508c | 357 | Adaptation::Ecap::XactionRep::vbContent(libecap::size_type o, libecap::size_type s) |
4d0854d4 | 358 | { |
e1e90d26 | 359 | // We may not be makingVb yet. It should be OK, but see vbContentShift(). |
ea76d91e | 360 | |
8679e6c2 | 361 | const BodyPipePointer &p = theVirginRep.raw().body_pipe; |
ea76d91e AR |
362 | Must(p != NULL); |
363 | ||
364 | // TODO: make MemBuf use size_t? | |
365 | const size_t haveSize = static_cast<size_t>(p->buf().contentSize()); | |
4d0854d4 | 366 | |
8679e6c2 AR |
367 | // convert to Squid types; XXX: check for overflow |
368 | const uint64_t offset = static_cast<uint64_t>(o); | |
369 | Must(offset <= haveSize); // equal iff at the end of content | |
370 | ||
371 | // nsize means no size limit: all content starting from offset | |
372 | const size_t size = s == libecap::nsize ? | |
26ac0430 | 373 | haveSize - offset : static_cast<size_t>(s); |
8679e6c2 | 374 | |
8679e6c2 AR |
375 | // XXX: optimize by making theBody a shared_ptr (see Area::FromTemp*() src) |
376 | return libecap::Area::FromTempBuffer(p->buf().content() + offset, | |
26ac0430 | 377 | min(static_cast<size_t>(haveSize - offset), size)); |
4d0854d4 AR |
378 | } |
379 | ||
380 | void | |
574b508c | 381 | Adaptation::Ecap::XactionRep::vbContentShift(libecap::size_type n) |
4d0854d4 | 382 | { |
e1e90d26 | 383 | // We may not be makingVb yet. It should be OK now, but if BodyPipe |
ea76d91e AR |
384 | // consume() requirements change, we would have to return empty vbContent |
385 | // until the adapter registers as a consumer | |
386 | ||
8679e6c2 AR |
387 | BodyPipePointer &p = theVirginRep.raw().body_pipe; |
388 | Must(p != NULL); | |
389 | const size_t size = static_cast<size_t>(n); // XXX: check for overflow | |
390 | const size_t haveSize = static_cast<size_t>(p->buf().contentSize()); // TODO: make MemBuf use size_t? | |
391 | p->consume(min(size, haveSize)); | |
4d0854d4 AR |
392 | } |
393 | ||
394 | void | |
574b508c | 395 | Adaptation::Ecap::XactionRep::noteAbContentDone(bool atEnd) |
4d0854d4 | 396 | { |
7477a343 AR |
397 | Must(proxyingAb == opOn && !abProductionFinished); |
398 | abProductionFinished = true; | |
399 | abProductionAtEnd = atEnd; // store until ready to stop producing ourselves | |
400 | debugs(93,5, HERE << "adapted body production ended"); | |
401 | moveAbContent(); | |
4d0854d4 AR |
402 | } |
403 | ||
8679e6c2 | 404 | void |
574b508c | 405 | Adaptation::Ecap::XactionRep::noteAbContentAvailable() |
4d0854d4 | 406 | { |
7477a343 | 407 | Must(proxyingAb == opOn && !abProductionFinished); |
8679e6c2 | 408 | moveAbContent(); |
4d0854d4 AR |
409 | } |
410 | ||
ea76d91e | 411 | #if 0 /* XXX: implement */ |
4d0854d4 | 412 | void |
574b508c | 413 | Adaptation::Ecap::XactionRep::setAdaptedBodySize(const libecap::BodySize &size) |
4d0854d4 AR |
414 | { |
415 | Must(answer().body_pipe != NULL); | |
8679e6c2 AR |
416 | if (size.known()) |
417 | answer().body_pipe->setBodySize(size.value()); | |
418 | // else the piped body size is unknown by default | |
4d0854d4 | 419 | } |
8679e6c2 | 420 | #endif |
4d0854d4 AR |
421 | |
422 | void | |
574b508c | 423 | Adaptation::Ecap::XactionRep::adaptationDelayed(const libecap::Delay &d) |
4d0854d4 AR |
424 | { |
425 | debugs(93,3, HERE << "adapter needs time: " << | |
26ac0430 | 426 | d.state << '/' << d.progress); |
4d0854d4 | 427 | // XXX: set timeout? |
fdc96a39 AR |
428 | } |
429 | ||
26ac0430 | 430 | void |
574b508c | 431 | Adaptation::Ecap::XactionRep::adaptationAborted() |
fdc96a39 | 432 | { |
fdc96a39 | 433 | tellQueryAborted(true); // should eCAP support retries? |
ea76d91e | 434 | mustStop("adaptationAborted"); |
fdc96a39 AR |
435 | } |
436 | ||
8679e6c2 | 437 | bool |
574b508c | 438 | Adaptation::Ecap::XactionRep::callable() const |
8679e6c2 AR |
439 | { |
440 | return !done(); | |
441 | } | |
442 | ||
26ac0430 | 443 | void |
574b508c | 444 | Adaptation::Ecap::XactionRep::noteMoreBodySpaceAvailable(RefCount<BodyPipe> bp) |
fdc96a39 | 445 | { |
ea76d91e AR |
446 | Must(proxyingAb == opOn); |
447 | moveAbContent(); | |
fdc96a39 AR |
448 | } |
449 | ||
26ac0430 | 450 | void |
574b508c | 451 | Adaptation::Ecap::XactionRep::noteBodyConsumerAborted(RefCount<BodyPipe> bp) |
fdc96a39 | 452 | { |
ea76d91e AR |
453 | Must(proxyingAb == opOn); |
454 | stopProducingFor(answer().body_pipe, false); | |
455 | Must(theMaster); | |
456 | theMaster->abStopMaking(); | |
457 | proxyingAb = opComplete; | |
fdc96a39 AR |
458 | } |
459 | ||
460 | void | |
574b508c | 461 | Adaptation::Ecap::XactionRep::noteMoreBodyDataAvailable(RefCount<BodyPipe> bp) |
fdc96a39 | 462 | { |
e1e90d26 | 463 | Must(makingVb == opOn); // or we would not be registered as a consumer |
fdc96a39 | 464 | Must(theMaster); |
8679e6c2 | 465 | theMaster->noteVbContentAvailable(); |
fdc96a39 AR |
466 | } |
467 | ||
468 | void | |
574b508c | 469 | Adaptation::Ecap::XactionRep::noteBodyProductionEnded(RefCount<BodyPipe> bp) |
fdc96a39 | 470 | { |
e1e90d26 | 471 | Must(makingVb == opOn); // or we would not be registered as a consumer |
fdc96a39 | 472 | Must(theMaster); |
8679e6c2 | 473 | theMaster->noteVbContentDone(true); |
e1e90d26 | 474 | vbProductionFinished = true; |
fdc96a39 AR |
475 | } |
476 | ||
477 | void | |
574b508c | 478 | Adaptation::Ecap::XactionRep::noteBodyProducerAborted(RefCount<BodyPipe> bp) |
fdc96a39 | 479 | { |
e1e90d26 | 480 | Must(makingVb == opOn); // or we would not be registered as a consumer |
8679e6c2 AR |
481 | Must(theMaster); |
482 | theMaster->noteVbContentDone(false); | |
e1e90d26 | 483 | vbProductionFinished = true; |
fdc96a39 AR |
484 | } |
485 | ||
486 | void | |
574b508c | 487 | Adaptation::Ecap::XactionRep::noteInitiatorAborted() |
fdc96a39 AR |
488 | { |
489 | mustStop("initiator aborted"); | |
490 | } | |
491 | ||
8679e6c2 AR |
492 | // get content from the adapter and put it into the adapted pipe |
493 | void | |
574b508c | 494 | Adaptation::Ecap::XactionRep::moveAbContent() |
8679e6c2 | 495 | { |
ea76d91e | 496 | Must(proxyingAb == opOn); |
8679e6c2 | 497 | const libecap::Area c = theMaster->abContent(0, libecap::nsize); |
7477a343 AR |
498 | debugs(93,5, HERE << "up to " << c.size << " bytes"); |
499 | if (c.size == 0 && abProductionFinished) { // no ab now and in the future | |
500 | stopProducingFor(answer().body_pipe, abProductionAtEnd); | |
501 | proxyingAb = opComplete; | |
502 | debugs(93,5, HERE << "last adapted body data retrieved"); | |
e1381638 | 503 | } else if (c.size > 0) { |
7477a343 AR |
504 | if (const size_t used = answer().body_pipe->putMoreData(c.start, c.size)) |
505 | theMaster->abContentShift(used); | |
506 | } | |
8679e6c2 AR |
507 | } |
508 | ||
509 | const char * | |
574b508c | 510 | Adaptation::Ecap::XactionRep::status() const |
fdc96a39 | 511 | { |
4d0854d4 AR |
512 | static MemBuf buf; |
513 | buf.reset(); | |
514 | ||
515 | buf.append(" [", 2); | |
516 | ||
e1e90d26 AR |
517 | if (makingVb) |
518 | buf.Printf("M%d", static_cast<int>(makingVb)); | |
519 | ||
520 | const BodyPipePointer &vp = theVirginRep.raw().body_pipe; | |
521 | if (!vp) | |
522 | buf.append(" !V", 3); | |
523 | else | |
524 | if (vp->stillConsuming(const_cast<XactionRep*>(this))) | |
525 | buf.append(" Vc", 3); | |
526 | else | |
527 | buf.append(" V?", 3); | |
528 | ||
529 | if (vbProductionFinished) | |
530 | buf.append(".", 1); | |
531 | ||
532 | ||
533 | buf.Printf(" A%d", static_cast<int>(proxyingAb)); | |
506a0530 | 534 | |
ea76d91e AR |
535 | if (proxyingAb == opOn) { |
536 | MessageRep *rep = dynamic_cast<MessageRep*>(theAnswerRep.get()); | |
537 | Must(rep); | |
f1a768b2 | 538 | const BodyPipePointer &ap = rep->raw().body_pipe; |
e1e90d26 AR |
539 | if (!ap) |
540 | buf.append(" !A", 3); | |
541 | else if (ap->stillProducing(const_cast<XactionRep*>(this))) | |
542 | buf.append(" Ap", 3); | |
543 | else | |
544 | buf.append(" A?", 3); | |
f1a768b2 | 545 | } |
4d0854d4 | 546 | |
52ed047a | 547 | buf.Printf(" %s%u]", id.Prefix, id.value); |
4d0854d4 AR |
548 | |
549 | buf.terminate(); | |
550 | ||
551 | return buf.content(); | |
fdc96a39 | 552 | } |