]> git.ipfire.org Git - thirdparty/squid.git/blame - src/BodyPipe.h
Author: Tsantilas Christos <chtsanti@users.sourceforge.net> , Alex Rousskov <rousskov...
[thirdparty/squid.git] / src / BodyPipe.h
CommitLineData
1b39caaa 1
2#ifndef SQUID_BODY_PIPE_H
3#define SQUID_BODY_PIPE_H
4
5#include "MemBuf.h"
882255af 6#include "base/AsyncCall.h"
d1e045c3 7#include "base/AsyncJob.h"
1b39caaa 8
9class BodyPipe;
10
11// Interface for those who want to produce body content for others.
12// BodyProducer is expected to create the BodyPipe.
13// One pipe cannot have more than one producer.
26ac0430
AJ
14class BodyProducer: virtual public AsyncJob
15{
16public:
17 BodyProducer():AsyncJob("BodyProducer") {}
18 virtual ~BodyProducer() {}
1b39caaa 19
26ac0430
AJ
20 virtual void noteMoreBodySpaceAvailable(RefCount<BodyPipe> bp) = 0;
21 virtual void noteBodyConsumerAborted(RefCount<BodyPipe> bp) = 0;
1b39caaa 22
26ac0430
AJ
23protected:
24 void stopProducingFor(RefCount<BodyPipe> &pipe, bool atEof);
1b39caaa 25};
26
27// Interface for those who want to consume body content from others.
28// BodyConsumer is expected to register with an existing BodyPipe
29// by calling BodyPipe::setConsumer().
30// One pipe cannot have more than one consumer.
26ac0430
AJ
31class BodyConsumer: virtual public AsyncJob
32{
33public:
34 BodyConsumer():AsyncJob("BodyConsumer") {}
35 virtual ~BodyConsumer() {}
36
37 virtual void noteMoreBodyDataAvailable(RefCount<BodyPipe> bp) = 0;
38 virtual void noteBodyProductionEnded(RefCount<BodyPipe> bp) = 0;
39 virtual void noteBodyProducerAborted(RefCount<BodyPipe> bp) = 0;
40
41protected:
42 void stopConsumingFrom(RefCount<BodyPipe> &pipe);
1b39caaa 43};
44
45// Makes raw buffer checkin/checkout interface efficient and exception-safe.
46// Either append or consume operations can be performed on a checkedout buffer.
26ac0430
AJ
47class BodyPipeCheckout
48{
49public:
50 friend class BodyPipe;
1b39caaa 51
26ac0430
AJ
52public:
53 BodyPipeCheckout(BodyPipe &pipe); // checks out
54 ~BodyPipeCheckout(); // aborts checkout unless checkedIn
1b39caaa 55
26ac0430 56 void checkIn();
1b39caaa 57
26ac0430
AJ
58public:
59 BodyPipe &pipe;
60 MemBuf &buf;
61 const uint64_t offset; // of current content, relative to the body start
1b39caaa 62
26ac0430
AJ
63protected:
64 const size_t checkedOutSize;
65 bool checkedIn;
1b39caaa 66
26ac0430
AJ
67private:
68 BodyPipeCheckout(const BodyPipeCheckout &); // prevent copying
69 BodyPipeCheckout &operator =(const BodyPipeCheckout &); // prevent assignment
1b39caaa 70};
71
72// Connects those who produces message body content with those who
73// consume it. For example, connects ConnStateData with FtpStateData OR
74// ICAPModXact with HttpStateData.
26ac0430
AJ
75class BodyPipe: public RefCountable
76{
77public:
78 typedef RefCount<BodyPipe> Pointer;
79 typedef BodyProducer Producer;
80 typedef BodyConsumer Consumer;
81 typedef BodyPipeCheckout Checkout;
1b39caaa 82
26ac0430 83 enum { MaxCapacity = SQUID_TCP_SO_RCVBUF };
1b39caaa 84
26ac0430 85 friend class BodyPipeCheckout;
1b39caaa 86
26ac0430
AJ
87public:
88 BodyPipe(Producer *aProducer);
89 ~BodyPipe(); // asserts that producer and consumer are cleared
1b39caaa 90
26ac0430
AJ
91 void setBodySize(uint64_t aSize); // set body size
92 bool bodySizeKnown() const { return theBodySize >= 0; }
93 uint64_t bodySize() const;
94 uint64_t consumedSize() const { return theGetSize; }
95 bool productionEnded() const { return !theProducer; }
1b39caaa 96
26ac0430
AJ
97 // called by producers
98 void clearProducer(bool atEof); // aborts or sends eof
99 size_t putMoreData(const char *buf, size_t size);
100 bool mayNeedMoreData() const { return !bodySizeKnown() || needsMoreData(); }
101 bool needsMoreData() const { return bodySizeKnown() && unproducedSize() > 0; }
102 uint64_t unproducedSize() const; // size of still unproduced data
103 bool stillProducing(const Producer *producer) const { return theProducer == producer; }
83c51da9 104 void expectProductionEndAfter(uint64_t extraSize); ///< sets or checks body size
1b39caaa 105
26ac0430
AJ
106 // called by consumers
107 bool setConsumerIfNotLate(Consumer *aConsumer);
108 void clearConsumer(); // aborts if still piping
109 size_t getMoreData(MemBuf &buf);
110 void consume(size_t size);
111 bool expectMoreAfter(uint64_t offset) const;
112 bool exhausted() const; // saw eof/abort and all data consumed
113 bool stillConsuming(const Consumer *consumer) const { return theConsumer == consumer; }
1b39caaa 114
26ac0430
AJ
115 // start or continue consuming when there is no consumer
116 void enableAutoConsumption();
1b39caaa 117
26ac0430 118 const MemBuf &buf() const { return theBuf; }
1b39caaa 119
26ac0430 120 const char *status() const; // for debugging only
1b39caaa 121
26ac0430
AJ
122protected:
123 // lower-level interface used by Checkout
124 MemBuf &checkOut(); // obtain raw buffer
125 void checkIn(Checkout &checkout); // return updated raw buffer
126 void undoCheckOut(Checkout &checkout); // undo checkout efffect
1b39caaa 127
26ac0430
AJ
128 void scheduleBodyDataNotification();
129 void scheduleBodyEndNotification();
1b39caaa 130
26ac0430
AJ
131 // keep counters in sync and notify producer or consumer
132 void postConsume(size_t size);
133 void postAppend(size_t size);
1b39caaa 134
26ac0430 135 void startAutoConsumption(); // delayed start of enabled consumption
5121d48e 136
26ac0430
AJ
137private:
138 int64_t theBodySize; // expected total content length, if known
139 Producer *theProducer; // content producer, if any
140 Consumer *theConsumer; // content consumer, if any
1b39caaa 141
26ac0430
AJ
142 uint64_t thePutSize; // ever-increasing total
143 uint64_t theGetSize; // ever-increasing total
1b39caaa 144
26ac0430 145 MemBuf theBuf; // produced but not yet consumed content, if any
1b39caaa 146
26ac0430
AJ
147 bool mustAutoConsume; // consume when there is no consumer
148 bool isCheckedOut; // to keep track of checkout violations
1b39caaa 149
26ac0430 150 CBDATA_CLASS2(BodyPipe);
1b39caaa 151};
152
153#endif /* SQUID_BODY_PIPE_H */