2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_BODY_PIPE_H
10 #define SQUID_BODY_PIPE_H
12 #include "base/AsyncJob.h"
13 #include "base/CbcPointer.h"
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.
22 class BodyProducer
: virtual public AsyncJob
25 typedef CbcPointer
<BodyProducer
> Pointer
;
27 BodyProducer():AsyncJob("BodyProducer") {}
28 virtual ~BodyProducer() {}
30 virtual void noteMoreBodySpaceAvailable(RefCount
<BodyPipe
> bp
) = 0;
31 virtual void noteBodyConsumerAborted(RefCount
<BodyPipe
> bp
) = 0;
34 void stopProducingFor(RefCount
<BodyPipe
> &, bool atEof
);
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.
42 class BodyConsumer
: virtual public AsyncJob
45 typedef CbcPointer
<BodyConsumer
> Pointer
;
47 BodyConsumer():AsyncJob("BodyConsumer") {}
48 virtual ~BodyConsumer() {}
50 virtual void noteMoreBodyDataAvailable(RefCount
<BodyPipe
> bp
) = 0;
51 virtual void noteBodyProductionEnded(RefCount
<BodyPipe
> bp
) = 0;
52 virtual void noteBodyProducerAborted(RefCount
<BodyPipe
> bp
) = 0;
55 void stopConsumingFrom(RefCount
<BodyPipe
> &);
58 /** Makes raw buffer checkin/checkout interface efficient and exception-safe.
59 * Either append or consume operations can be performed on a checkedout buffer.
61 class BodyPipeCheckout
64 friend class BodyPipe
;
67 BodyPipeCheckout(BodyPipe
&); // checks out
68 ~BodyPipeCheckout(); // aborts checkout unless checkedIn
75 const uint64_t offset
; // of current content, relative to the body start
78 const size_t checkedOutSize
;
82 BodyPipeCheckout(const BodyPipeCheckout
&); // prevent copying
83 BodyPipeCheckout
&operator =(const BodyPipeCheckout
&); // prevent assignment
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.
90 class BodyPipe
: public RefCountable
92 MEMPROXY_CLASS(BodyPipe
);
95 typedef RefCount
<BodyPipe
> Pointer
;
96 typedef BodyProducer Producer
;
97 typedef BodyConsumer Consumer
;
98 typedef BodyPipeCheckout Checkout
;
100 enum { MaxCapacity
= 64*1024 };
102 friend class BodyPipeCheckout
;
105 BodyPipe(Producer
*aProducer
);
106 ~BodyPipe(); // asserts that producer and consumer are cleared
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
; }
112 uint64_t producedSize() const { return thePutSize
; }
113 bool productionEnded() const { return !theProducer
; }
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
121 bool stillProducing(const Producer::Pointer
&producer
) const { return theProducer
== producer
; }
122 void expectProductionEndAfter(uint64_t extraSize
); ///< sets or checks body size
124 // called by consumers
125 bool setConsumerIfNotLate(const Consumer::Pointer
&aConsumer
);
126 void clearConsumer(); // aborts if still piping
127 void expectNoConsumption(); ///< there will be no more setConsumer() calls
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
132 bool stillConsuming(const Consumer::Pointer
&consumer
) const { return theConsumer
== consumer
; }
134 // start or continue consuming when there is no consumer
135 void enableAutoConsumption();
137 const MemBuf
&buf() const { return theBuf
; }
139 const char *status() const; // for debugging only
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
147 void scheduleBodyDataNotification();
148 void scheduleBodyEndNotification();
150 // keep counters in sync and notify producer or consumer
151 void postConsume(size_t size
);
152 void postAppend(size_t size
);
154 void startAutoConsumption(); // delayed start of enabled consumption
157 int64_t theBodySize
; // expected total content length, if known
158 Producer::Pointer theProducer
; // content producer, if any
159 Consumer::Pointer theConsumer
; // content consumer, if any
161 uint64_t thePutSize
; // ever-increasing total
162 uint64_t theGetSize
; // ever-increasing total
164 MemBuf theBuf
; // produced but not yet consumed content, if any
166 bool mustAutoConsume
; // consume when there is no consumer
167 bool abortedConsumption
; ///< called BodyProducer::noteBodyConsumerAborted
168 bool isCheckedOut
; // to keep track of checkout violations
171 #endif /* SQUID_BODY_PIPE_H */