2
#ifndef SQUID_BODY_PIPE_H
3
#define SQUID_BODY_PIPE_H
10
// Interface for those who want to produce body content for others.
11
// BodyProducer is expected to create the BodyPipe.
12
// One pipe cannot have more than one producer.
15
virtual ~BodyProducer() {}
17
virtual void noteMoreBodySpaceAvailable(BodyPipe &bp) = 0;
18
virtual void noteBodyConsumerAborted(BodyPipe &bp) = 0;
21
void stopProducingFor(RefCount<BodyPipe> &pipe, bool atEof);
24
// Interface for those who want to consume body content from others.
25
// BodyConsumer is expected to register with an existing BodyPipe
26
// by calling BodyPipe::setConsumer().
27
// One pipe cannot have more than one consumer.
30
virtual ~BodyConsumer() {}
32
virtual void noteMoreBodyDataAvailable(BodyPipe &bp) = 0;
33
virtual void noteBodyProductionEnded(BodyPipe &bp) = 0;
34
virtual void noteBodyProducerAborted(BodyPipe &bp) = 0;
37
void stopConsumingFrom(RefCount<BodyPipe> &pipe);
40
// Makes raw buffer checkin/checkout interface efficient and exception-safe.
41
// Either append or consume operations can be performed on a checkedout buffer.
42
class BodyPipeCheckout {
44
friend class BodyPipe;
47
BodyPipeCheckout(BodyPipe &pipe); // checks out
48
~BodyPipeCheckout(); // aborts checkout unless checkedIn
55
const size_t offset; // of current content, relative to the body start
58
const size_t checkedOutSize;
62
BodyPipeCheckout(const BodyPipeCheckout &); // prevent copying
63
BodyPipeCheckout &operator =(const BodyPipeCheckout &); // prevent assignment
66
// Connects those who produces message body content with those who
67
// consume it. For example, connects ConnStateData with FtpStateData OR
68
// ICAPModXact with HttpStateData.
69
class BodyPipe: public RefCountable {
71
typedef RefCount<BodyPipe> Pointer;
72
typedef BodyProducer Producer;
73
typedef BodyConsumer Consumer;
74
typedef BodyPipeCheckout Checkout;
76
enum { MaxCapacity = SQUID_TCP_SO_RCVBUF };
78
friend class BodyPipeCheckout;
81
BodyPipe(Producer *aProducer);
82
~BodyPipe(); // asserts that producer and consumer are cleared
84
void setBodySize(size_t aSize); // set body size
85
bool bodySizeKnown() const { return theBodySize >= 0; }
86
size_t bodySize() const;
87
size_t consumedSize() const { return theGetSize; }
88
bool productionEnded() const { return !theProducer; }
90
// called by producers
91
void clearProducer(bool atEof); // aborts or sends eof
92
size_t putMoreData(const char *buf, size_t size);
93
bool mayNeedMoreData() const { return !bodySizeKnown() || needsMoreData(); }
94
bool needsMoreData() const { return bodySizeKnown() && unproducedSize() > 0; }
95
size_t unproducedSize() const; // size of still unproduced data
97
// called by consumers
98
bool setConsumerIfNotLate(Consumer *aConsumer);
99
void clearConsumer(); // aborts if still piping
100
size_t getMoreData(MemBuf &buf);
101
void consume(size_t size);
102
bool expectMoreAfter(size_t offset) const;
103
bool exhausted() const; // saw eof/abort and all data consumed
105
// start or continue consuming when there is no consumer
106
void enableAutoConsumption();
108
const MemBuf &buf() const { return theBuf; }
110
const char *status() const; // for debugging only
113
// lower-level interface used by Checkout
114
MemBuf &checkOut(); // obtain raw buffer
115
void checkIn(Checkout &checkout); // return updated raw buffer
116
void undoCheckOut(Checkout &checkout); // undo checkout efffect
118
void scheduleBodyEndNotification();
120
// keep counters in sync and notify producer or consumer
121
void postConsume(size_t size);
122
void postAppend(size_t size);
124
public: /* public to enable callbacks, but treat as private */
126
/* these methods are calling producer and sibscriber note*()
127
* callbacks with this BodyPipe as a parameter, which allows
128
* a single producer or consumer to support multiple pipes. */
130
void tellMoreBodySpaceAvailable();
131
void tellBodyConsumerAborted();
132
void tellMoreBodyDataAvailable();
133
void tellBodyProductionEnded();
134
void tellBodyProducerAborted();
136
AsyncCallWrapper(91,5, BodyPipe, tellMoreBodySpaceAvailable);
137
AsyncCallWrapper(91,5, BodyPipe, tellBodyConsumerAborted);
138
AsyncCallWrapper(91,5, BodyPipe, tellMoreBodyDataAvailable);
139
AsyncCallWrapper(91,5, BodyPipe, tellBodyProductionEnded);
140
AsyncCallWrapper(91,5, BodyPipe, tellBodyProducerAborted);
143
ssize_t theBodySize; // expected total content length, if known
144
Producer *theProducer; // content producer, if any
145
Consumer *theConsumer; // content consumer, if any
147
size_t thePutSize; // ever-increasing total
148
size_t theGetSize; // ever-increasing total
150
MemBuf theBuf; // produced but not yet consumed content, if any
152
bool mustAutoConsume; // consume when there is no consumer
153
bool isCheckedOut; // to keep track of checkout violations
155
CBDATA_CLASS2(BodyPipe);
158
#endif /* SQUID_BODY_PIPE_H */