/* * Copyright (C) 2007-2019 Xagasoft, All rights reserved. * * This file is part of the libbu++ library and is released under the * terms of the license contained in the file LICENSE. */ #ifndef BU_CLIENT_BUF_H #define BU_CLIENT_BUF_H #include "bu/stream.h" #include "bu/streamstack.h" #include "bu/queuebuf.h" #include "bu/mutex.h" namespace Bu { /** * ClientBuf represents two buffered I/O channels, input and output. Each * is stored in its own Bu::QueueBuf. One side is client oriented and can * have filters applied ala Bu::StreamStack. The other is server oriented * and is accesesed raw. Both must be accessed via accessor objects. * * Direct access to the buffers isn't allowed, instead you must select a * perspective. client() provides an accessor where reading consumes data * coming from the socket and writing provides data to write to the socket. * server() works in reverse, writing is writing data from the socket that * we have just read, reading is reading data that should be written to the * socket. * * client() provides a filtered access view of the data, while server() is * unfiltered. */ class ClientBuf { public: class ClientAccess : public Bu::Stream { friend class Bu::ClientBuf; private: ClientAccess( Bu::ClientBuf &rBuf ); public: virtual ~ClientAccess(); virtual void close(); virtual size read( void *pBuf, size iBytes ); virtual size peek( void *pData, int iBytes, int iOffset=0 ); virtual size write( const void *pBuf, size iBytes ); using Stream::write; virtual size tell(); virtual void seek( size offset ); virtual void setPos( size pos ); virtual void setPosEnd( size pos ); virtual bool isEos(); virtual bool isOpen(); virtual void flush(); virtual bool canRead(); virtual bool canWrite(); virtual bool isReadable(); virtual bool isWritable(); virtual bool isSeekable(); virtual bool isBlocking(); virtual void setBlocking( bool bBlocking=true ); virtual void setSize( size iSize ); virtual size getSize() const; virtual size getBlockSize() const; virtual Bu::String getLocation() const; private: Bu::ClientBuf &rBuf; Bu::QueueBuf qbPeek; mutable Bu::Mutex mAccess; }; class ServerAccess : public Bu::Stream { friend class Bu::ClientBuf; private: ServerAccess( Bu::ClientBuf &rBuf ); public: virtual ~ServerAccess(); virtual void close(); virtual size read( void *pBuf, size iBytes ); virtual size peek( void *pData, int iBytes, int iOffset=0 ); virtual size write( const void *pBuf, size iBytes ); using Stream::write; virtual size tell(); virtual void seek( size offset ); virtual void setPos( size pos ); virtual void setPosEnd( size pos ); virtual bool isEos(); virtual bool isOpen(); virtual void flush(); virtual bool canRead(); virtual bool canWrite(); virtual bool isReadable(); virtual bool isWritable(); virtual bool isSeekable(); virtual bool isBlocking(); virtual void setBlocking( bool bBlocking=true ); virtual void setSize( size iSize ); virtual size getSize() const; virtual size getBlockSize() const; virtual Bu::String getLocation() const; private: Bu::ClientBuf &rBuf; }; private: class ClientAccessRaw : public Bu::Stream { friend class Bu::ClientBuf; private: ClientAccessRaw( Bu::ClientBuf &rBuf ); public: virtual ~ClientAccessRaw(); virtual void close(); virtual size read( void *pBuf, size iBytes ); virtual size write( const void *pBuf, size iBytes ); using Stream::write; virtual size tell(); virtual void seek( size offset ); virtual void setPos( size pos ); virtual void setPosEnd( size pos ); virtual bool isEos(); virtual bool isOpen(); virtual void flush(); virtual bool canRead(); virtual bool canWrite(); virtual bool isReadable(); virtual bool isWritable(); virtual bool isSeekable(); virtual bool isBlocking(); virtual void setBlocking( bool bBlocking=true ); virtual void setSize( size iSize ); virtual size getSize() const; virtual size getBlockSize() const; virtual Bu::String getLocation() const; private: Bu::ClientBuf &rBuf; }; public: ClientBuf(); virtual ~ClientBuf(); /** * Access the client access side. Use directly, do NOT copy or store. */ ClientAccess &client(); /** * Access the server access side. Use directly, do NOT copy or store. */ ServerAccess &server(); private: ClientAccessRaw accClientRaw; ServerAccess accServer; //Bu::StreamStack accClientFiltered; ClientAccess accClient; Bu::QueueBuf qbOutput; Bu::QueueBuf qbInput; Bu::Mutex mOutput; Bu::Mutex mInput; friend class Bu::ClientBuf::ClientAccess; friend class Bu::ClientBuf::ClientAccessRaw; friend class Bu::ClientBuf::ServerAccess; }; } #endif