]>
Commit | Line | Data |
---|---|---|
bbc27441 | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
bbc27441 AJ |
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 | ||
ff9d9458 FC |
9 | #ifndef SQUID_SRC_BODYPIPE_H |
10 | #define SQUID_SRC_BODYPIPE_H | |
1b39caaa | 11 | |
d1e045c3 | 12 | #include "base/AsyncJob.h" |
4299f876 | 13 | #include "base/CbcPointer.h" |
602d9612 | 14 | #include "MemBuf.h" |
1b39caaa | 15 | |
16 | class BodyPipe; | |
17 | ||
d1c37eab AJ |
18 | /** Interface for those who want to produce body content for others. |
19 | * BodyProducer is expected to create the BodyPipe. | |
20 | * One pipe cannot have more than one producer. | |
21 | */ | |
26ac0430 AJ |
22 | class BodyProducer: virtual public AsyncJob |
23 | { | |
24 | public: | |
4299f876 AR |
25 | typedef CbcPointer<BodyProducer> Pointer; |
26 | ||
26ac0430 | 27 | BodyProducer():AsyncJob("BodyProducer") {} |
337b9aa4 | 28 | ~BodyProducer() override {} |
1b39caaa | 29 | |
26ac0430 AJ |
30 | virtual void noteMoreBodySpaceAvailable(RefCount<BodyPipe> bp) = 0; |
31 | virtual void noteBodyConsumerAborted(RefCount<BodyPipe> bp) = 0; | |
1b39caaa | 32 | |
26ac0430 | 33 | protected: |
3be43416 | 34 | void stopProducingFor(RefCount<BodyPipe> &, bool atEof); |
1b39caaa | 35 | }; |
36 | ||
d1c37eab AJ |
37 | /** Interface for those who want to consume body content from others. |
38 | * BodyConsumer is expected to register with an existing BodyPipe | |
39 | * by calling BodyPipe::setConsumer(). | |
40 | * One pipe cannot have more than one consumer. | |
41 | */ | |
26ac0430 AJ |
42 | class BodyConsumer: virtual public AsyncJob |
43 | { | |
44 | public: | |
4299f876 AR |
45 | typedef CbcPointer<BodyConsumer> Pointer; |
46 | ||
26ac0430 | 47 | BodyConsumer():AsyncJob("BodyConsumer") {} |
337b9aa4 | 48 | ~BodyConsumer() override {} |
26ac0430 AJ |
49 | |
50 | virtual void noteMoreBodyDataAvailable(RefCount<BodyPipe> bp) = 0; | |
51 | virtual void noteBodyProductionEnded(RefCount<BodyPipe> bp) = 0; | |
52 | virtual void noteBodyProducerAborted(RefCount<BodyPipe> bp) = 0; | |
53 | ||
54 | protected: | |
3be43416 | 55 | void stopConsumingFrom(RefCount<BodyPipe> &); |
1b39caaa | 56 | }; |
57 | ||
d1c37eab AJ |
58 | /** Makes raw buffer checkin/checkout interface efficient and exception-safe. |
59 | * Either append or consume operations can be performed on a checkedout buffer. | |
60 | */ | |
26ac0430 AJ |
61 | class BodyPipeCheckout |
62 | { | |
63 | public: | |
64 | friend class BodyPipe; | |
1b39caaa | 65 | |
26ac0430 | 66 | public: |
3be43416 | 67 | BodyPipeCheckout(BodyPipe &); // checks out |
26ac0430 | 68 | ~BodyPipeCheckout(); // aborts checkout unless checkedIn |
1b39caaa | 69 | |
26ac0430 | 70 | void checkIn(); |
1b39caaa | 71 | |
26ac0430 | 72 | public: |
3be43416 | 73 | BodyPipe &thePipe; |
26ac0430 AJ |
74 | MemBuf &buf; |
75 | const uint64_t offset; // of current content, relative to the body start | |
1b39caaa | 76 | |
26ac0430 AJ |
77 | protected: |
78 | const size_t checkedOutSize; | |
79 | bool checkedIn; | |
1b39caaa | 80 | |
26ac0430 AJ |
81 | private: |
82 | BodyPipeCheckout(const BodyPipeCheckout &); // prevent copying | |
83 | BodyPipeCheckout &operator =(const BodyPipeCheckout &); // prevent assignment | |
1b39caaa | 84 | }; |
85 | ||
d1c37eab AJ |
86 | /** Connects those who produces message body content with those who |
87 | * consume it. For example, connects ConnStateData with FtpStateData OR | |
88 | * ICAPModXact with HttpStateData. | |
89 | */ | |
26ac0430 AJ |
90 | class BodyPipe: public RefCountable |
91 | { | |
27186b2c | 92 | MEMPROXY_CLASS(BodyPipe); |
5c2f68b7 | 93 | |
26ac0430 AJ |
94 | public: |
95 | typedef RefCount<BodyPipe> Pointer; | |
96 | typedef BodyProducer Producer; | |
97 | typedef BodyConsumer Consumer; | |
98 | typedef BodyPipeCheckout Checkout; | |
1b39caaa | 99 | |
0c060c02 | 100 | static constexpr size_t MaxCapacity = 64*1024; |
1b39caaa | 101 | |
26ac0430 | 102 | friend class BodyPipeCheckout; |
1b39caaa | 103 | |
26ac0430 AJ |
104 | public: |
105 | BodyPipe(Producer *aProducer); | |
337b9aa4 | 106 | ~BodyPipe() override; // asserts that producer and consumer are cleared |
1b39caaa | 107 | |
26ac0430 AJ |
108 | void setBodySize(uint64_t aSize); // set body size |
109 | bool bodySizeKnown() const { return theBodySize >= 0; } | |
110 | uint64_t bodySize() const; | |
111 | uint64_t consumedSize() const { return theGetSize; } | |
dc0017a9 | 112 | uint64_t producedSize() const { return thePutSize; } |
26ac0430 | 113 | bool productionEnded() const { return !theProducer; } |
1b39caaa | 114 | |
26ac0430 AJ |
115 | // called by producers |
116 | void clearProducer(bool atEof); // aborts or sends eof | |
117 | size_t putMoreData(const char *buf, size_t size); | |
118 | bool mayNeedMoreData() const { return !bodySizeKnown() || needsMoreData(); } | |
119 | bool needsMoreData() const { return bodySizeKnown() && unproducedSize() > 0; } | |
120 | uint64_t unproducedSize() const; // size of still unproduced data | |
4299f876 | 121 | bool stillProducing(const Producer::Pointer &producer) const { return theProducer == producer; } |
83c51da9 | 122 | void expectProductionEndAfter(uint64_t extraSize); ///< sets or checks body size |
1b39caaa | 123 | |
26ac0430 | 124 | // called by consumers |
4299f876 | 125 | bool setConsumerIfNotLate(const Consumer::Pointer &aConsumer); |
26ac0430 | 126 | void clearConsumer(); // aborts if still piping |
abe286b8 | 127 | void expectNoConsumption(); ///< there will be no more setConsumer() calls |
26ac0430 AJ |
128 | size_t getMoreData(MemBuf &buf); |
129 | void consume(size_t size); | |
130 | bool expectMoreAfter(uint64_t offset) const; | |
131 | bool exhausted() const; // saw eof/abort and all data consumed | |
4299f876 | 132 | bool stillConsuming(const Consumer::Pointer &consumer) const { return theConsumer == consumer; } |
1b39caaa | 133 | |
b599471b | 134 | /// start or continue consuming when producing without consumer |
26ac0430 | 135 | void enableAutoConsumption(); |
1b39caaa | 136 | |
26ac0430 | 137 | const MemBuf &buf() const { return theBuf; } |
1b39caaa | 138 | |
26ac0430 | 139 | const char *status() const; // for debugging only |
1b39caaa | 140 | |
26ac0430 AJ |
141 | protected: |
142 | // lower-level interface used by Checkout | |
143 | MemBuf &checkOut(); // obtain raw buffer | |
144 | void checkIn(Checkout &checkout); // return updated raw buffer | |
145 | void undoCheckOut(Checkout &checkout); // undo checkout efffect | |
1b39caaa | 146 | |
26ac0430 AJ |
147 | void scheduleBodyDataNotification(); |
148 | void scheduleBodyEndNotification(); | |
1b39caaa | 149 | |
26ac0430 AJ |
150 | // keep counters in sync and notify producer or consumer |
151 | void postConsume(size_t size); | |
152 | void postAppend(size_t size); | |
1b39caaa | 153 | |
b599471b | 154 | void startAutoConsumptionIfNeeded(); |
5121d48e | 155 | |
26ac0430 AJ |
156 | private: |
157 | int64_t theBodySize; // expected total content length, if known | |
4299f876 AR |
158 | Producer::Pointer theProducer; // content producer, if any |
159 | Consumer::Pointer theConsumer; // content consumer, if any | |
1b39caaa | 160 | |
26ac0430 AJ |
161 | uint64_t thePutSize; // ever-increasing total |
162 | uint64_t theGetSize; // ever-increasing total | |
1b39caaa | 163 | |
26ac0430 | 164 | MemBuf theBuf; // produced but not yet consumed content, if any |
1b39caaa | 165 | |
b599471b | 166 | bool mustAutoConsume; ///< keep theBuf empty when producing without consumer |
abe286b8 | 167 | bool abortedConsumption; ///< called BodyProducer::noteBodyConsumerAborted |
26ac0430 | 168 | bool isCheckedOut; // to keep track of checkout violations |
1b39caaa | 169 | }; |
170 | ||
ff9d9458 | 171 | #endif /* SQUID_SRC_BODYPIPE_H */ |
f53969cc | 172 |