summaryrefslogtreecommitdiffstats
path: root/CryptoPP/network.h
diff options
context:
space:
mode:
Diffstat (limited to 'CryptoPP/network.h')
-rw-r--r--CryptoPP/network.h235
1 files changed, 235 insertions, 0 deletions
diff --git a/CryptoPP/network.h b/CryptoPP/network.h
new file mode 100644
index 000000000..96cd4567e
--- /dev/null
+++ b/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