Squid Web Cache master
Loading...
Searching...
No Matches
XactionRep.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 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 eCAP Interface */
10
11#include "squid.h"
12#include "adaptation/Answer.h"
16#include "base/AsyncJobCalls.h"
17#include "base/TextException.h"
18#include "format/Format.h"
19#include "HttpReply.h"
20#include "MasterXaction.h"
21#include "sbuf/StringConvert.h"
22
23#if HAVE_LIBECAP_COMMON_AREA_H
24#include <libecap/common/area.h>
25#endif
26#if HAVE_LIBECAP_COMMON_DELAY_H
27#include <libecap/common/delay.h>
28#endif
29#if HAVE_LIBECAP_COMMON_NAMED_VALUES_H
30#include <libecap/common/named_values.h>
31#endif
32#if HAVE_LIBECAP_COMMON_NAMES_H
33#include <libecap/common/names.h>
34#endif
35
37
39class OptionsExtractor: public libecap::NamedValueVisitor
40{
41public:
42 typedef libecap::Name Name;
43 typedef libecap::Area Area;
44
45 OptionsExtractor(HttpHeader &aMeta): meta(aMeta) {}
46
47 // libecap::NamedValueVisitor API
48 void visit(const Name &name, const Area &value) override {
49 meta.putExt(name.image().c_str(), value.toString().c_str());
50 }
51
53};
54
56 Http::Message *virginHeader, HttpRequest *virginCause, AccessLogEntry::Pointer &alp,
57 const Adaptation::ServicePointer &aService):
58 AsyncJob("Adaptation::Ecap::XactionRep"),
59 Adaptation::Initiate("Adaptation::Ecap::XactionRep"),
60 theService(aService),
61 theVirginRep(virginHeader), theCauseRep(nullptr),
62 makingVb(opUndecided), proxyingAb(opUndecided),
63 adaptHistoryId(-1),
64 vbProductionFinished(false),
65 abProductionFinished(false), abProductionAtEnd(false),
66 al(alp)
67{
68 if (virginCause)
69 theCauseRep = new MessageRep(virginCause);
70}
71
73{
74 assert(!theMaster);
75 delete theCauseRep;
76 theAnswerRep.reset();
77}
78
79void
81{
82 Must(!theMaster);
83 Must(x);
84 theMaster = x;
85}
86
89{
90 Must(theService != nullptr);
91 return *theService;
92}
93
94const libecap::Area
95Adaptation::Ecap::XactionRep::option(const libecap::Name &name) const
96{
97 if (name == libecap::metaClientIp)
98 return clientIpValue();
99 if (name == libecap::metaUserName)
100 return usernameValue();
102 return masterxSharedValue(name);
103
104 // TODO: metaServerIp, metaAuthenticatedUser, and metaAuthenticatedGroups
105
106 // If the name is unknown, metaValue returns an empty area
107 return metaValue(name);
108}
109
110void
111Adaptation::Ecap::XactionRep::visitEachOption(libecap::NamedValueVisitor &visitor) const
112{
113 if (const libecap::Area value = clientIpValue())
114 visitor.visit(libecap::metaClientIp, value);
115 if (const libecap::Area value = usernameValue())
116 visitor.visit(libecap::metaUserName, value);
117
119 const libecap::Name name(Adaptation::Config::masterx_shared_name);
120 if (const libecap::Area value = masterxSharedValue(name))
121 visitor.visit(name, value);
122 }
123
124 visitEachMetaHeader(visitor);
125
126 // TODO: metaServerIp, metaAuthenticatedUser, and metaAuthenticatedGroups
127}
128
129const libecap::Area
131{
132 const HttpRequest *request = dynamic_cast<const HttpRequest*>(theCauseRep ?
133 theCauseRep->raw().header : theVirginRep.raw().header);
134 Must(request);
135 // TODO: move this logic into HttpRequest::clientIp(bool) and
136 // HttpRequest::clientIpString(bool) and reuse everywhere
137 if (TheConfig.send_client_ip && request) {
138 Ip::Address client_addr;
139#if FOLLOW_X_FORWARDED_FOR
141 client_addr = request->indirect_client_addr;
142 } else
143#endif
144 client_addr = request->client_addr;
145 if (!client_addr.isAnyAddr() && !client_addr.isNoAddr()) {
146 char ntoabuf[MAX_IPSTRLEN] = "";
147 client_addr.toStr(ntoabuf,MAX_IPSTRLEN);
148 return libecap::Area::FromTempBuffer(ntoabuf, strlen(ntoabuf));
149 }
150 }
151 return libecap::Area();
152}
153
154const libecap::Area
156{
157#if USE_AUTH
158 const HttpRequest *request = dynamic_cast<const HttpRequest*>(theCauseRep ?
159 theCauseRep->raw().header : theVirginRep.raw().header);
160 Must(request);
161 if (request->auth_user_request != nullptr) {
162 if (char const *name = request->auth_user_request->username())
163 return libecap::Area::FromTempBuffer(name, strlen(name));
164 else if (request->extacl_user.size() > 0)
165 return libecap::Area::FromTempBuffer(request->extacl_user.rawBuf(),
166 request->extacl_user.size());
167 }
168#endif
169 return libecap::Area();
170}
171
172const libecap::Area
173Adaptation::Ecap::XactionRep::masterxSharedValue(const libecap::Name &sharedName) const
174{
175 const HttpRequest *request = dynamic_cast<const HttpRequest*>(theCauseRep ?
176 theCauseRep->raw().header : theVirginRep.raw().header);
177 Must(request);
178 if (sharedName.known()) { // must check to avoid empty names matching unset cfg
179 Adaptation::History::Pointer ah = request->adaptHistory(false);
180 if (ah != nullptr) {
181 String name, value;
182 if (ah->getXxRecord(name, value))
183 return libecap::Area::FromTempBuffer(value.rawBuf(), value.size());
184 }
185 }
186 return libecap::Area();
187}
188
189const libecap::Area
190Adaptation::Ecap::XactionRep::metaValue(const libecap::Name &name) const
191{
192 HttpRequest *request = dynamic_cast<HttpRequest*>(theCauseRep ?
193 theCauseRep->raw().header : theVirginRep.raw().header);
194 Must(request);
195 HttpReply *reply = dynamic_cast<HttpReply*>(theVirginRep.raw().header);
196
197 if (name.known()) { // must check to avoid empty names matching unset cfg
198 for (const auto &h: Adaptation::Config::metaHeaders()) {
199 if (name == h->key().toStdString()) {
200 SBuf matched;
201 if (h->match(request, reply, al, matched))
202 return libecap::Area::FromTempString(matched.toStdString());
203 else
204 return libecap::Area();
205 }
206 }
207 }
208
209 return libecap::Area();
210}
211
212void
213Adaptation::Ecap::XactionRep::visitEachMetaHeader(libecap::NamedValueVisitor &visitor) const
214{
215 HttpRequest *request = dynamic_cast<HttpRequest*>(theCauseRep ?
216 theCauseRep->raw().header : theVirginRep.raw().header);
217 Must(request);
218 HttpReply *reply = dynamic_cast<HttpReply*>(theVirginRep.raw().header);
219
220 for (const auto &h: Adaptation::Config::metaHeaders()) {
221 SBuf matched;
222 if (h->match(request, reply, al, matched)) {
223 const libecap::Name name(h->key().toStdString());
224 const libecap::Area value = libecap::Area::FromTempString(matched.toStdString());
225 visitor.visit(name, value);
226 }
227 }
228}
229
230void
232{
233 Must(theMaster);
234
235 if (!theVirginRep.raw().body_pipe)
236 makingVb = opNever; // there is nothing to deliver
237
238 HttpRequest *request = dynamic_cast<HttpRequest*> (theCauseRep ?
239 theCauseRep->raw().header : theVirginRep.raw().header);
240 Must(request);
241
242 HttpReply *reply = dynamic_cast<HttpReply*>(theVirginRep.raw().header);
243
245 if (ah != nullptr) {
246 // retrying=false because ecap never retries transactions
247 adaptHistoryId = ah->recordXactStart(service().cfg().key, current_time, false);
248 SBuf matched;
249 for (const auto &h: Adaptation::Config::metaHeaders()) {
250 if (h->match(request, reply, al, matched)) {
251 if (ah->metaHeaders == nullptr)
252 ah->metaHeaders = new NotePairs();
253 if (!ah->metaHeaders->hasPair(h->key(), matched))
254 ah->metaHeaders->add(h->key(), matched);
255 }
256 }
257 }
258
259 theMaster->start();
260}
261
262void
264{
265 // clear body_pipes, if any
266 // this code does not maintain proxying* and canAccessVb states; should it?
267
268 if (theAnswerRep) {
269 BodyPipe::Pointer body_pipe = answer().body_pipe;
270 if (body_pipe != nullptr) {
271 Must(body_pipe->stillProducing(this));
272 stopProducingFor(body_pipe, false);
273 }
274 }
275
276 BodyPipe::Pointer &body_pipe = theVirginRep.raw().body_pipe;
277 if (body_pipe != nullptr && body_pipe->stillConsuming(this))
278 stopConsumingFrom(body_pipe);
279
280 terminateMaster();
281
282 const HttpRequest *request = dynamic_cast<const HttpRequest*>(theCauseRep ?
283 theCauseRep->raw().header : theVirginRep.raw().header);
284 Must(request);
286 if (ah != nullptr && adaptHistoryId >= 0)
287 ah->recordXactFinish(adaptHistoryId);
288
290}
291
292void
294{
295 // go async to gain exception protection and done()-based job destruction
297 AsyncCall::Pointer call = asyncCall(93, 5, "Adaptation::Ecap::XactionRep::doResume",
299 ScheduleCallHere(call);
300}
301
304void
306{
307 Must(theMaster);
308 theMaster->resume();
309}
310
311libecap::Message &
313{
314 return theVirginRep;
315}
316
317const libecap::Message &
319{
320 Must(theCauseRep != nullptr);
321 return *theCauseRep;
322}
323
324libecap::Message &
326{
327 Must(theAnswerRep);
328 return *theAnswerRep;
329}
330
333{
334 MessageRep *rep = dynamic_cast<MessageRep*>(theAnswerRep.get());
335 Must(rep);
336 return rep->raw();
337}
338
339void
341{
342 if (theMaster) {
343 AdapterXaction x = theMaster;
344 theMaster.reset();
345 x->stop();
346 }
347}
348
349bool
351{
352 return makingVb >= opComplete && proxyingAb >= opComplete &&
354}
355
356// stops receiving virgin and enables auto-consumption, dropping any vb bytes
357void
359{
360 debugs(93,4, "sink for " << reason << "; status:" << status());
361
362 // we reset raw().body_pipe when we are done, so use this one for checking
363 const BodyPipePointer &permPipe = theVirginRep.raw().header->body_pipe;
364 if (permPipe != nullptr)
365 permPipe->enableAutoConsumption();
366
367 forgetVb(reason);
368}
369
370// stops receiving virgin but preserves it for others to use
371void
373{
374 debugs(93,4, "preserve for " << reason << "; status:" << status());
375
376 // we reset raw().body_pipe when we are done, so use this one for checking
377 const BodyPipePointer &permPipe = theVirginRep.raw().header->body_pipe;
378 if (permPipe != nullptr) {
379 // if libecap consumed, we cannot preserve
380 Must(!permPipe->consumedSize());
381 }
382
383 forgetVb(reason);
384}
385
386// disassociates us from vb; the last step of sinking or preserving vb
387void
389{
390 debugs(93,9, "forget vb " << reason << "; status:" << status());
391
392 BodyPipePointer &p = theVirginRep.raw().body_pipe;
393 if (p != nullptr && p->stillConsuming(this))
394 stopConsumingFrom(p);
395
396 if (makingVb == opUndecided)
397 makingVb = opNever;
398 else if (makingVb == opOn)
399 makingVb = opComplete;
400}
401
402void
404{
405 debugs(93,3, status());
406 Must(proxyingAb == opUndecided);
407 proxyingAb = opNever;
408
409 preserveVb("useVirgin");
410
411 Http::Message *clone = theVirginRep.raw().header->clone();
412 // check that clone() copies the pipe so that we do not have to
413 Must(!theVirginRep.raw().header->body_pipe == !clone->body_pipe);
414
415 updateHistory(clone);
416 sendAnswer(Answer::Forward(clone));
417 Must(done());
418}
419
420void
421Adaptation::Ecap::XactionRep::useAdapted(const libecap::shared_ptr<libecap::Message> &m)
422{
423 debugs(93,3, status());
424 Must(m);
425 theAnswerRep = m;
426 Must(proxyingAb == opUndecided);
427
428 Http::Message *msg = answer().header;
429 updateSources(msg);
430 if (!theAnswerRep->body()) { // final, bodyless answer
431 proxyingAb = opNever;
432 updateHistory(msg);
433 sendAnswer(Answer::Forward(msg));
434 } else { // got answer headers but need to handle body
435 proxyingAb = opOn;
436 Must(!msg->body_pipe); // only host can set body pipes
437 MessageRep *rep = dynamic_cast<MessageRep*>(theAnswerRep.get());
438 Must(rep);
439 rep->tieBody(this); // sets us as a producer
440 Must(msg->body_pipe != nullptr); // check tieBody
441
442 updateHistory(msg);
443 sendAnswer(Answer::Forward(msg));
444
445 debugs(93,4, "adapter will produce body" << status());
446 theMaster->abMake(); // libecap will produce
447 }
448}
449
450void
452{
453 debugs(93,3, status());
454 Must(proxyingAb == opUndecided);
455 proxyingAb = opNever;
456
457 sinkVb("blockVirgin");
458
459 updateHistory(nullptr);
460 sendAnswer(Answer::Block(StringToSBuf(service().cfg().key)));
461 Must(done());
462}
463
466void
468{
469 if (!theMaster) // all updates rely on being able to query the adapter
470 return;
471
472 const HttpRequest *request = dynamic_cast<const HttpRequest*>(theCauseRep ?
473 theCauseRep->raw().header : theVirginRep.raw().header);
474 Must(request);
475
476 // TODO: move common ICAP/eCAP logic to Adaptation::Xaction or similar
477 // TODO: optimize Area-to-String conversion
478
479 // update the cross-transactional database if needed
480 if (const char *xxNameStr = Adaptation::Config::masterx_shared_name) {
481 Adaptation::History::Pointer ah = request->adaptHistory(true);
482 if (ah != nullptr) {
483 libecap::Name xxName(xxNameStr); // TODO: optimize?
484 if (const libecap::Area val = theMaster->option(xxName))
485 ah->updateXxRecord(xxNameStr, val.toString().c_str());
486 }
487 }
488
489 // update the adaptation plan if needed
490 if (service().cfg().routing) {
491 if (const libecap::Area services = theMaster->option(libecap::metaNextServices)) {
492 Adaptation::History::Pointer ah = request->adaptHistory(true);
493 if (ah != nullptr)
494 ah->updateNextServices(services.toString().c_str());
495 }
496 } // TODO: else warn (occasionally!) if we got libecap::metaNextServices
497
498 // Store received meta headers for adapt::<last_h logformat code use.
499 // If we already have stored headers from a previous adaptation transaction
500 // related to the same master transaction, they will be replaced.
502 if (ah != nullptr) {
503 HttpHeader meta(hoReply);
504 OptionsExtractor extractor(meta);
505 theMaster->visitEachOption(extractor);
506 ah->recordMeta(&meta);
507 }
508
509 // Add just-created history to the adapted/cloned request that lacks it.
510 if (HttpRequest *adaptedReq = dynamic_cast<HttpRequest*>(adapted))
511 adaptedReq->adaptHistoryImport(*request);
512}
513
514void
516{
517 Must(makingVb == opUndecided);
518 // if adapter does not need vb, we do not need to send it
519 sinkVb("vbDiscard");
520 Must(makingVb == opNever);
521}
522
523void
525{
526 Must(makingVb == opUndecided);
527 BodyPipePointer &p = theVirginRep.raw().body_pipe;
528 Must(p != nullptr);
529 Must(p->setConsumerIfNotLate(this)); // to deliver vb, we must receive vb
530 makingVb = opOn;
531}
532
533void
535{
536 Must(makingVb == opOn);
537 // if adapter does not need vb, we do not need to receive it
538 sinkVb("vbStopMaking");
539 Must(makingVb == opComplete);
540}
541
542void
544{
545 Must(makingVb == opOn); // cannot make more if done proxying
546 // we cannot guarantee more vb, but we can check that there is a chance
547 const BodyPipePointer &p = theVirginRep.raw().body_pipe;
548 Must(p != nullptr && p->stillConsuming(this)); // we are plugged in
549 Must(!p->productionEnded() && p->mayNeedMoreData()); // and may get more
550}
551
552libecap::Area
553Adaptation::Ecap::XactionRep::vbContent(libecap::size_type o, libecap::size_type s)
554{
555 // We may not be makingVb yet. It should be OK, but see vbContentShift().
556
557 const BodyPipePointer &p = theVirginRep.raw().body_pipe;
558 Must(p != nullptr);
559
560 // TODO: make MemBuf use size_t?
561 const size_t haveSize = static_cast<size_t>(p->buf().contentSize());
562
563 // convert to Squid types; XXX: check for overflow
564 const uint64_t offset = static_cast<uint64_t>(o);
565 Must(offset <= haveSize); // equal iff at the end of content
566
567 // nsize means no size limit: all content starting from offset
568 const size_t size = s == libecap::nsize ?
569 haveSize - offset : static_cast<size_t>(s);
570
571 // XXX: optimize by making theBody a shared_ptr (see Area::FromTemp*() src)
572 return libecap::Area::FromTempBuffer(p->buf().content() + offset,
573 min(static_cast<size_t>(haveSize - offset), size));
574}
575
576void
578{
579 // We may not be makingVb yet. It should be OK now, but if BodyPipe
580 // consume() requirements change, we would have to return empty vbContent
581 // until the adapter registers as a consumer
582
583 BodyPipePointer &p = theVirginRep.raw().body_pipe;
584 Must(p != nullptr);
585 const size_t size = static_cast<size_t>(n); // XXX: check for overflow
586 const size_t haveSize = static_cast<size_t>(p->buf().contentSize()); // TODO: make MemBuf use size_t?
587 p->consume(min(size, haveSize));
588}
589
590void
592{
593 Must(proxyingAb == opOn && !abProductionFinished);
594 abProductionFinished = true;
595 abProductionAtEnd = atEnd; // store until ready to stop producing ourselves
596 debugs(93,5, "adapted body production ended");
597 moveAbContent();
598}
599
600void
602{
603 Must(proxyingAb == opOn && !abProductionFinished);
604 moveAbContent();
605}
606
607#if 0 /* XXX: implement */
608void
609Adaptation::Ecap::XactionRep::setAdaptedBodySize(const libecap::BodySize &size)
610{
611 Must(answer().body_pipe != NULL);
612 if (size.known())
613 answer().body_pipe->setBodySize(size.value());
614 // else the piped body size is unknown by default
615}
616#endif
617
618void
620{
621 debugs(93,3, "adapter needs time: " <<
622 d.state << '/' << d.progress);
623 // XXX: set timeout?
624}
625
626void
628{
629 tellQueryAborted(true); // should eCAP support retries?
630 mustStop("adaptationAborted");
631}
632
633void
635{
636 Must(proxyingAb == opOn);
637 moveAbContent();
638}
639
640void
642{
643 Must(proxyingAb == opOn);
644 stopProducingFor(answer().body_pipe, false);
645 Must(theMaster);
646 theMaster->abStopMaking();
647 proxyingAb = opComplete;
648}
649
650void
652{
653 Must(makingVb == opOn); // or we would not be registered as a consumer
654 Must(theMaster);
655 theMaster->noteVbContentAvailable();
656}
657
658void
660{
661 Must(makingVb == opOn); // or we would not be registered as a consumer
662 Must(theMaster);
663 theMaster->noteVbContentDone(true);
664 vbProductionFinished = true;
665}
666
667void
669{
670 Must(makingVb == opOn); // or we would not be registered as a consumer
671 Must(theMaster);
672 theMaster->noteVbContentDone(false);
673 vbProductionFinished = true;
674}
675
676void
678{
679 mustStop("initiator aborted");
680}
681
682// get content from the adapter and put it into the adapted pipe
683void
685{
686 Must(proxyingAb == opOn);
687 const libecap::Area c = theMaster->abContent(0, libecap::nsize);
688 debugs(93,5, "up to " << c.size << " bytes");
689 if (c.size == 0 && abProductionFinished) { // no ab now and in the future
690 stopProducingFor(answer().body_pipe, abProductionAtEnd);
691 proxyingAb = opComplete;
692 debugs(93,5, "last adapted body data retrieved");
693 } else if (c.size > 0) {
694 if (const size_t used = answer().body_pipe->putMoreData(c.start, c.size))
695 theMaster->abContentShift(used);
696 }
697}
698
699const char *
701{
702 static MemBuf buf;
703 buf.reset();
704
705 buf.append(" [", 2);
706
707 if (makingVb)
708 buf.appendf("M%d", static_cast<int>(makingVb));
709
710 const BodyPipePointer &vp = theVirginRep.raw().body_pipe;
711 if (!vp)
712 buf.append(" !V", 3);
713 else if (vp->stillConsuming(const_cast<XactionRep*>(this)))
714 buf.append(" Vc", 3);
715 else
716 buf.append(" V?", 3);
717
718 if (vbProductionFinished)
719 buf.append(".", 1);
720
721 buf.appendf(" A%d", static_cast<int>(proxyingAb));
722
723 if (proxyingAb == opOn) {
724 MessageRep *rep = dynamic_cast<MessageRep*>(theAnswerRep.get());
725 Must(rep);
726 const BodyPipePointer &ap = rep->raw().body_pipe;
727 if (!ap)
728 buf.append(" !A", 3);
729 else if (ap->stillProducing(const_cast<XactionRep*>(this)))
730 buf.append(" Ap", 3);
731 else
732 buf.append(" A?", 3);
733 }
734
735 buf.appendf(" %s%u]", id.prefix(), id.value);
736
737 buf.terminate();
738
739 return buf.content();
740}
741
742void
744{
745 adapted->sources |= service().cfg().connectionEncryption ? Http::Message::srcEcaps : Http::Message::srcEcap;
746
747 // Update masterXaction object for adapted HTTP requests.
748 if (HttpRequest *adaptedReq = dynamic_cast<HttpRequest*>(adapted)) {
749 HttpRequest *request = dynamic_cast<HttpRequest*> (theCauseRep ?
750 theCauseRep->raw().header : theVirginRep.raw().header);
751 Must(request);
752 adaptedReq->masterXaction = request->masterXaction;
753 }
754}
755
#define ScheduleCallHere(call)
Definition AsyncCall.h:166
RefCount< AsyncCallT< Dialer > > asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition AsyncCall.h:156
@ hoReply
Definition HttpHeader.h:37
int size
Definition ModDevPoll.cc:70
SBuf StringToSBuf(const String &s)
create a new SBuf from a String by copying contents
#define Must(condition)
#define assert(EX)
Definition assert.h:17
#define CBDATA_NAMESPACED_CLASS_INIT(namespace, type)
Definition cbdata.h:333
static Answer Block(const SBuf &aRule)
create an akBlock answer
Definition Answer.cc:35
static Answer Forward(Http::Message *aMsg)
create an akForward answer
Definition Answer.cc:26
static int send_client_ip
Definition Config.h:47
static int use_indirect_client
Definition Config.h:49
static char * masterx_shared_name
Definition Config.h:45
static Notes & metaHeaders()
The list of configured meta headers.
Definition Config.cc:35
Adaptation::Message & raw()
Definition MessageRep.h:171
void tieBody(Ecap::XactionRep *x)
void preserveVb(const char *reason)
const char * status() const override
internal cleanup; do not call directly
bool doneAll() const override
whether positive goal has been reached
void noteMoreBodySpaceAvailable(RefCount< BodyPipe > bp) override
void noteMoreBodyDataAvailable(RefCount< BodyPipe > bp) override
void visitEachMetaHeader(libecap::NamedValueVisitor &visitor) const
Return the adaptation meta headers and their values.
const libecap::Area clientIpValue() const
void noteInitiatorAborted() override
void forgetVb(const char *reason)
void start() override
called by AsyncStart; do not call directly
const libecap::Area metaValue(const libecap::Name &name) const
Return the adaptation meta header value for the given header "name".
const libecap::Area usernameValue() const
void adaptationDelayed(const libecap::Delay &) override
void noteAbContentAvailable() override
void adaptationAborted() override
const libecap::Area option(const libecap::Name &name) const override
Definition XactionRep.cc:95
XactionRep(Http::Message *virginHeader, HttpRequest *virginCause, AccessLogEntry::Pointer &alp, const Adaptation::ServicePointer &service)
Definition XactionRep.cc:55
libecap::Message & adapted() override
void noteAbContentDone(bool atEnd) override
void updateHistory(Http::Message *adapted)
void visitEachOption(libecap::NamedValueVisitor &visitor) const override
void updateSources(Http::Message *adapted)
const libecap::Area masterxSharedValue(const libecap::Name &name) const
Adaptation::Message & answer()
void noteBodyProducerAborted(RefCount< BodyPipe > bp) override
void noteBodyProductionEnded(RefCount< BodyPipe > bp) override
libecap::Message & virgin() override
const libecap::Message & cause() override
void master(const AdapterXaction &aMaster)
Definition XactionRep.cc:80
libecap::shared_ptr< libecap::adapter::Xaction > AdapterXaction
Definition XactionRep.h:44
libecap::Area vbContent(libecap::size_type offset, libecap::size_type size) override
void sinkVb(const char *reason)
void useAdapted(const libecap::shared_ptr< libecap::Message > &msg) override
void noteBodyConsumerAborted(RefCount< BodyPipe > bp) override
void vbContentShift(libecap::size_type size) override
int recordXactStart(const String &serviceId, const timeval &when, bool retrying)
record the start of a xact, return xact history ID
Definition History.cc:51
void updateXxRecord(const char *name, const String &value)
sets or resets a cross-transactional database record
Definition History.cc:105
NotePairs::Pointer metaHeaders
Definition History.h:66
bool getXxRecord(String &name, String &value) const
returns true and fills the record fields iff there is a db record
Definition History.cc:111
void updateNextServices(const String &services)
sets or resets next services for the Adaptation::Iterator to notice
Definition History.cc:121
void recordMeta(const HttpHeader *lm)
store the last meta header fields received from the adaptation service
Definition History.cc:140
void recordXactFinish(int hid)
record the end of a xact identified by its history ID
Definition History.cc:61
void swanSong() override
Definition Initiate.cc:62
BodyPipePointer body_pipe
Definition Message.h:46
virtual bool doneAll() const
whether positive goal has been reached
Definition AsyncJob.cc:112
char const * username() const
bool stillConsuming(const Consumer::Pointer &consumer) const
Definition BodyPipe.h:132
const MemBuf & buf() const
Definition BodyPipe.h:137
void consume(size_t size)
Definition BodyPipe.cc:309
uint64_t consumedSize() const
Definition BodyPipe.h:111
bool setConsumerIfNotLate(const Consumer::Pointer &aConsumer)
Definition BodyPipe.cc:228
bool stillProducing(const Producer::Pointer &producer) const
Definition BodyPipe.h:121
bool productionEnded() const
Definition BodyPipe.h:113
bool mayNeedMoreData() const
Definition BodyPipe.h:118
void enableAutoConsumption()
start or continue consuming when producing without consumer
Definition BodyPipe.cc:316
void putExt(const char *name, const char *value)
Adaptation::History::Pointer adaptHistory(bool createIfNone=false) const
Returns possibly nil history, creating it if requested.
MasterXaction::Pointer masterXaction
the master transaction this request belongs to. Never nil.
Ip::Address indirect_client_addr
String extacl_user
Adaptation::History::Pointer adaptLogHistory() const
Returns possibly nil history, creating it if adapt. logging is enabled.
Auth::UserRequest::Pointer auth_user_request
Ip::Address client_addr
common parts of HttpRequest and HttpReply
Definition Message.h:26
@ srcEcap
eCAP service that uses insecure libraries/daemons
Definition Message.h:42
@ srcEcaps
eCAP service that is considered secure; currently unused
Definition Message.h:36
uint32_t sources
The message sources.
Definition Message.h:99
HttpHeader header
Definition Message.h:74
BodyPipe::Pointer body_pipe
optional pipeline to receive message body
Definition Message.h:97
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition Address.cc:804
bool isNoAddr() const
Definition Address.cc:304
bool isAnyAddr() const
Definition Address.cc:190
void append(const char *c, int sz) override
Definition MemBuf.cc:209
char * content()
start of the added data
Definition MemBuf.h:41
mb_size_t contentSize() const
available data size
Definition MemBuf.h:47
void reset()
Definition MemBuf.cc:129
void terminate()
Definition MemBuf.cc:241
void add(const SBuf &key, const SBuf &value)
Definition Notes.cc:322
bool hasPair(const SBuf &key, const SBuf &value) const
Definition Notes.cc:375
a libecap Visitor for converting adapter transaction options to HttpHeader
Definition XactionRep.cc:40
HttpHeader & meta
where to put extracted options
Definition XactionRep.cc:52
libecap::Name Name
Definition XactionRep.cc:42
void visit(const Name &name, const Area &value) override
Definition XactionRep.cc:48
OptionsExtractor(HttpHeader &aMeta)
Definition XactionRep.cc:45
libecap::Area Area
Definition XactionRep.cc:43
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition Packable.h:61
Definition SBuf.h:94
std::string toStdString() const
std::string export function
Definition SBuf.h:585
char const * rawBuf() const
Definition SquidString.h:87
size_type size() const
Definition SquidString.h:74
A const & min(A const &lhs, A const &rhs)
#define debugs(SECTION, LEVEL, CONTENT)
Definition Stream.h:192
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition forward.h:25
Config TheConfig
Definition Config.cc:16
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
Definition gadgets.cc:18
#define NULL
Definition types.h:145