summaryrefslogtreecommitdiff
path: root/network.h
diff options
context:
space:
mode:
authorweidai <weidai11@users.noreply.github.com>2006-04-06 21:20:25 +0000
committerweidai <weidai11@users.noreply.github.com>2006-04-06 21:20:25 +0000
commit6aacd0a0de141d218710374018412cca1893ad9d (patch)
tree34dba126863f587607debfecab883867f5f2d3dd /network.h
parent254b0f0d4d307221e0328b8f4e892a9bc0d93765 (diff)
downloadcryptopp-git-6aacd0a0de141d218710374018412cca1893ad9d.tar.gz
merge in changes by denis bider and fix compile on gcc 3.4.4 and MSVC 6
Diffstat (limited to 'network.h')
-rw-r--r--network.h99
1 files changed, 81 insertions, 18 deletions
diff --git a/network.h b/network.h
index 6efbf991..4373862d 100644
--- a/network.h
+++ b/network.h
@@ -4,21 +4,62 @@
#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, CallStack const& 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>
+class CRYPTOPP_NO_VTABLE NonblockingSource : public AutoSignaling<Source>, public LimitedBandwidth
{
public:
NonblockingSource(BufferedTransformation *attachment)
- : m_messageEndSent(false) {Detach(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. */
- virtual size_t GeneralPump2(lword &byteCount, bool blockingOutput=true, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n') =0;
+ 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')
{
@@ -35,8 +76,14 @@ public:
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;
+ bool m_messageEndSent, m_doPumpBlocked, m_blockedBySpeedLimit;
};
//! Network Receiver
@@ -57,6 +104,7 @@ 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
@@ -64,9 +112,11 @@ public:
};
//! 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
+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
@@ -79,11 +129,19 @@ public:
For example: while (sink.TimedFlush(0) > 0) {}
\return number of bytes flushed
*/
- virtual lword TimedFlush(unsigned long maxTime, size_t targetSize=0) =0;
+ 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
@@ -94,7 +152,9 @@ public:
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
};
#ifdef HIGHRES_TIMER_AVAILABLE
@@ -105,14 +165,14 @@ class CRYPTOPP_NO_VTABLE NetworkSource : public NonblockingSource
public:
NetworkSource(BufferedTransformation *attachment);
- unsigned int GetMaxWaitObjectCount() const
- {return GetReceiver().GetMaxWaitObjectCount() + AttachedTransformation()->GetMaxWaitObjectCount();}
- void GetWaitObjects(WaitObjectContainer &container);
+ unsigned int GetMaxWaitObjectCount() const;
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
- size_t GeneralPump2(lword &byteCount, bool blockingOutput=true, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n');
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();}
@@ -128,35 +188,38 @@ class CRYPTOPP_NO_VTABLE NetworkSink : public NonblockingSink
public:
NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound);
- unsigned int GetMaxWaitObjectCount() const
- {return GetSender().GetMaxWaitObjectCount();}
- void GetWaitObjects(WaitObjectContainer &container)
- {if (m_wasBlocked || !m_buffer.IsEmpty()) AccessSender().GetWaitObjects(container);}
+ unsigned int GetMaxWaitObjectCount() const;
+ void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
- lword TimedFlush(unsigned long maxTime, size_t targetSize = 0);
-
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();}
+ 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 {return m_maxObservedSpeed;}
+ 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;