diff options
Diffstat (limited to 'lib/cryptopp/network.h')
-rw-r--r-- | lib/cryptopp/network.h | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/lib/cryptopp/network.h b/lib/cryptopp/network.h new file mode 100644 index 000000000..96cd4567e --- /dev/null +++ b/lib/cryptopp/network.h @@ -0,0 +1,235 @@ +#ifndef CRYPTOPP_NETWORK_H +#define CRYPTOPP_NETWORK_H + +#include "config.h" + +#ifdef HIGHRES_TIMER_AVAILABLE + +#include "filters.h" +#include "hrtimer.h" + +#include <deque> + +NAMESPACE_BEGIN(CryptoPP) + +class LimitedBandwidth +{ +public: + LimitedBandwidth(lword maxBytesPerSecond = 0) + : m_maxBytesPerSecond(maxBytesPerSecond), m_timer(Timer::MILLISECONDS) + , m_nextTransceiveTime(0) + { m_timer.StartTimer(); } + + lword GetMaxBytesPerSecond() const + { return m_maxBytesPerSecond; } + + void SetMaxBytesPerSecond(lword v) + { m_maxBytesPerSecond = v; } + + lword ComputeCurrentTransceiveLimit(); + + double TimeToNextTransceive(); + + void NoteTransceive(lword size); + +public: + /*! GetWaitObjects() must be called despite the 0 return from GetMaxWaitObjectCount(); + the 0 is because the ScheduleEvent() method is used instead of adding a wait object */ + unsigned int GetMaxWaitObjectCount() const { return 0; } + void GetWaitObjects(WaitObjectContainer &container, const CallStack &callStack); + +private: + lword m_maxBytesPerSecond; + + typedef std::deque<std::pair<double, lword> > OpQueue; + OpQueue m_ops; + + Timer m_timer; + double m_nextTransceiveTime; + + void ComputeNextTransceiveTime(); + double GetCurTimeAndCleanUp(); +}; + +//! a Source class that can pump from a device for a specified amount of time. +class CRYPTOPP_NO_VTABLE NonblockingSource : public AutoSignaling<Source>, public LimitedBandwidth +{ +public: + NonblockingSource(BufferedTransformation *attachment) + : m_messageEndSent(false) , m_doPumpBlocked(false), m_blockedBySpeedLimit(false) {Detach(attachment);} + + //! \name NONBLOCKING SOURCE + //@{ + + //! pump up to maxSize bytes using at most maxTime milliseconds + /*! If checkDelimiter is true, pump up to delimiter, which itself is not extracted or pumped. */ + size_t GeneralPump2(lword &byteCount, bool blockingOutput=true, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n'); + + lword GeneralPump(lword maxSize=LWORD_MAX, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n') + { + GeneralPump2(maxSize, true, maxTime, checkDelimiter, delimiter); + return maxSize; + } + lword TimedPump(unsigned long maxTime) + {return GeneralPump(LWORD_MAX, maxTime);} + lword PumpLine(byte delimiter='\n', lword maxSize=1024) + {return GeneralPump(maxSize, INFINITE_TIME, true, delimiter);} + + size_t Pump2(lword &byteCount, bool blocking=true) + {return GeneralPump2(byteCount, blocking, blocking ? INFINITE_TIME : 0);} + size_t PumpMessages2(unsigned int &messageCount, bool blocking=true); + //@} + +protected: + virtual size_t DoPump(lword &byteCount, bool blockingOutput, + unsigned long maxTime, bool checkDelimiter, byte delimiter) =0; + + bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; } + +private: + bool m_messageEndSent, m_doPumpBlocked, m_blockedBySpeedLimit; +}; + +//! Network Receiver +class CRYPTOPP_NO_VTABLE NetworkReceiver : public Waitable +{ +public: + virtual bool MustWaitToReceive() {return false;} + virtual bool MustWaitForResult() {return false;} + //! receive data from network source, returns whether result is immediately available + virtual bool Receive(byte* buf, size_t bufLen) =0; + virtual unsigned int GetReceiveResult() =0; + virtual bool EofReceived() const =0; +}; + +class CRYPTOPP_NO_VTABLE NonblockingSinkInfo +{ +public: + virtual ~NonblockingSinkInfo() {} + virtual size_t GetMaxBufferSize() const =0; + virtual size_t GetCurrentBufferSize() const =0; + virtual bool EofPending() const =0; + //! compute the current speed of this sink in bytes per second + virtual float ComputeCurrentSpeed() =0; + //! get the maximum observed speed of this sink in bytes per second + virtual float GetMaxObservedSpeed() const =0; +}; + +//! a Sink class that queues input and can flush to a device for a specified amount of time. +class CRYPTOPP_NO_VTABLE NonblockingSink : public Sink, public NonblockingSinkInfo, public LimitedBandwidth +{ +public: + NonblockingSink() : m_blockedBySpeedLimit(false) {} + + bool IsolatedFlush(bool hardFlush, bool blocking); + + //! flush to device for no more than maxTime milliseconds + /*! This function will repeatedly attempt to flush data to some device, until + the queue is empty, or a total of maxTime milliseconds have elapsed. + If maxTime == 0, at least one attempt will be made to flush some data, but + it is likely that not all queued data will be flushed, even if the device + is ready to receive more data without waiting. If you want to flush as much data + as possible without waiting for the device, call this function in a loop. + For example: while (sink.TimedFlush(0) > 0) {} + \return number of bytes flushed + */ + lword TimedFlush(unsigned long maxTime, size_t targetSize = 0); + + virtual void SetMaxBufferSize(size_t maxBufferSize) =0; + //! set a bound which will cause sink to flush if exceeded by GetCurrentBufferSize() + virtual void SetAutoFlushBound(size_t bound) =0; + +protected: + virtual lword DoFlush(unsigned long maxTime, size_t targetSize) = 0; + + bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; } + +private: + bool m_blockedBySpeedLimit; +}; + +//! Network Sender +class CRYPTOPP_NO_VTABLE NetworkSender : public Waitable +{ +public: + virtual bool MustWaitToSend() {return false;} + virtual bool MustWaitForResult() {return false;} + virtual void Send(const byte* buf, size_t bufLen) =0; + virtual unsigned int GetSendResult() =0; + virtual bool MustWaitForEof() {return false;} + virtual void SendEof() =0; + virtual bool EofSent() {return false;} // implement if MustWaitForEof() == true +}; + +//! Network Source +class CRYPTOPP_NO_VTABLE NetworkSource : public NonblockingSource +{ +public: + NetworkSource(BufferedTransformation *attachment); + + unsigned int GetMaxWaitObjectCount() const; + void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack); + + bool SourceExhausted() const {return m_dataBegin == m_dataEnd && GetReceiver().EofReceived();} + +protected: + size_t DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter); + + virtual NetworkReceiver & AccessReceiver() =0; + const NetworkReceiver & GetReceiver() const {return const_cast<NetworkSource *>(this)->AccessReceiver();} + +private: + SecByteBlock m_buf; + size_t m_putSize, m_dataBegin, m_dataEnd; + bool m_waitingForResult, m_outputBlocked; +}; + +//! Network Sink +class CRYPTOPP_NO_VTABLE NetworkSink : public NonblockingSink +{ +public: + NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound); + + unsigned int GetMaxWaitObjectCount() const; + void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack); + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + + void SetMaxBufferSize(size_t maxBufferSize) {m_maxBufferSize = maxBufferSize; m_buffer.SetNodeSize(UnsignedMin(maxBufferSize, 16U*1024U+256U));} + void SetAutoFlushBound(size_t bound) {m_autoFlushBound = bound;} + + size_t GetMaxBufferSize() const {return m_maxBufferSize;} + size_t GetCurrentBufferSize() const {return (size_t)m_buffer.CurrentSize();} + + void ClearBuffer() { m_buffer.Clear(); } + + bool EofPending() const { return m_eofState > EOF_NONE && m_eofState < EOF_DONE; } + + //! compute the current speed of this sink in bytes per second + float ComputeCurrentSpeed(); + //! get the maximum observed speed of this sink in bytes per second + float GetMaxObservedSpeed() const; + +protected: + lword DoFlush(unsigned long maxTime, size_t targetSize); + + virtual NetworkSender & AccessSender() =0; + const NetworkSender & GetSender() const {return const_cast<NetworkSink *>(this)->AccessSender();} + +private: + enum EofState { EOF_NONE, EOF_PENDING_SEND, EOF_PENDING_DELIVERY, EOF_DONE }; + + size_t m_maxBufferSize, m_autoFlushBound; + bool m_needSendResult, m_wasBlocked; + EofState m_eofState; + ByteQueue m_buffer; + size_t m_skipBytes; + Timer m_speedTimer; + float m_byteCountSinceLastTimerReset, m_currentSpeed, m_maxObservedSpeed; +}; + +NAMESPACE_END + +#endif // #ifdef HIGHRES_TIMER_AVAILABLE + +#endif |