]> git.ipfire.org Git - thirdparty/squid.git/blame - src/BodyPipe.h
Make BodyPipe::MaxCapacity constexpr (#1748)
[thirdparty/squid.git] / src / BodyPipe.h
CommitLineData
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
16class 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
22class BodyProducer: virtual public AsyncJob
23{
24public:
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 33protected:
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
42class BodyConsumer: virtual public AsyncJob
43{
44public:
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
54protected:
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
61class BodyPipeCheckout
62{
63public:
64 friend class BodyPipe;
1b39caaa 65
26ac0430 66public:
3be43416 67 BodyPipeCheckout(BodyPipe &); // checks out
26ac0430 68 ~BodyPipeCheckout(); // aborts checkout unless checkedIn
1b39caaa 69
26ac0430 70 void checkIn();
1b39caaa 71
26ac0430 72public:
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
77protected:
78 const size_t checkedOutSize;
79 bool checkedIn;
1b39caaa 80
26ac0430
AJ
81private:
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
90class BodyPipe: public RefCountable
91{
27186b2c 92 MEMPROXY_CLASS(BodyPipe);
5c2f68b7 93
26ac0430
AJ
94public:
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
104public:
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
141protected:
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
156private:
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