
// interface for those who want to provide body content to BodyPipe
class BodyProvider {
	public:
		virtual BodyProvider() {}

		virtual provideMoreBody(BodyPipe *pipe) = 0;
		virtual noteBodyConsumerAbort(BodyPipe *pipe) = 0;
};

// interface for those who want to consume body content from BodyPipe
class BodyConsumer {
	public:
		virtual BodyConsumer() {}

		virtual consumeMoreBody(BodyPipe *pipe) = 0;
		virtual noteBodyProviderAbort(BodyPipe *pipe) = 0;
};

// Connects those who produce message body content with those who
// consume it. For example, connects ConnStateData and FtpStateData OR
// ICAPClientReqmodPrecache and HttpStateData.
class BodyPipe: public RefCountable {
	public:
		typedef RefCount<BodyPipe> Pointer;

	public:
		BodyPipe(size_t aLength, Provider *aProvider);
		~BodyPipe(); // clear provider and consumer first

		// called by providers
		void clearProvider(bool keepPiping);
		size_t spaceSize() const;
		size_t putMoreData(const char *buf, size_t size);

		// called by consumers
		void setConsumer(Consumer *aConsumer);
		void clearConsumer(bool keepPiping);
		size_t dataSize() const;
		size_t getMoreData(MemBuf &buf);

	private:
		const size_t theLength;  // expected content length
		Provider *theProvider;   // content provider, if any
		Provider *theConsumer;   // content consumer, if any

		size_t thePutSize; // ever-increasing total
		size_t theGetSize; // ever-increasing total

		MemBuf theBuf; // provided but not yet consumed content, if any

		CBDATA_CLASS2(BodyPipe);
};

