00001 #ifndef CRYPTOPP_NETWORK_H
00002 #define CRYPTOPP_NETWORK_H
00003
00004 #include "filters.h"
00005 #include "hrtimer.h"
00006
00007 #include <deque>
00008
00009 NAMESPACE_BEGIN(CryptoPP)
00010
00011 class LimitedBandwidth
00012 {
00013 public:
00014 LimitedBandwidth(lword maxBytesPerSecond = 0)
00015 : m_maxBytesPerSecond(maxBytesPerSecond), m_timer(Timer::MILLISECONDS)
00016 , m_nextTransceiveTime(0)
00017 { m_timer.StartTimer(); }
00018
00019 lword GetMaxBytesPerSecond() const
00020 { return m_maxBytesPerSecond; }
00021
00022 void SetMaxBytesPerSecond(lword v)
00023 { m_maxBytesPerSecond = v; }
00024
00025 lword ComputeCurrentTransceiveLimit();
00026
00027 double TimeToNextTransceive();
00028
00029 void NoteTransceive(lword size);
00030
00031 public:
00032
00033
00034 unsigned int GetMaxWaitObjectCount() const { return 0; }
00035 void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
00036
00037 private:
00038 lword m_maxBytesPerSecond;
00039
00040 typedef std::deque<std::pair<double, lword> > OpQueue;
00041 OpQueue m_ops;
00042
00043 Timer m_timer;
00044 double m_nextTransceiveTime;
00045
00046 void ComputeNextTransceiveTime();
00047 double GetCurTimeAndCleanUp();
00048 };
00049
00050
00051 class CRYPTOPP_NO_VTABLE NonblockingSource : public AutoSignaling<Source>, public LimitedBandwidth
00052 {
00053 public:
00054 NonblockingSource(BufferedTransformation *attachment)
00055 : m_messageEndSent(false) , m_doPumpBlocked(false), m_blockedBySpeedLimit(false) {Detach(attachment);}
00056
00057
00058
00059
00060
00061
00062 size_t GeneralPump2(lword &byteCount, bool blockingOutput=true, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n');
00063
00064 lword GeneralPump(lword maxSize=LWORD_MAX, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n')
00065 {
00066 GeneralPump2(maxSize, true, maxTime, checkDelimiter, delimiter);
00067 return maxSize;
00068 }
00069 lword TimedPump(unsigned long maxTime)
00070 {return GeneralPump(LWORD_MAX, maxTime);}
00071 lword PumpLine(byte delimiter='\n', lword maxSize=1024)
00072 {return GeneralPump(maxSize, INFINITE_TIME, true, delimiter);}
00073
00074 size_t Pump2(lword &byteCount, bool blocking=true)
00075 {return GeneralPump2(byteCount, blocking, blocking ? INFINITE_TIME : 0);}
00076 size_t PumpMessages2(unsigned int &messageCount, bool blocking=true);
00077
00078
00079 protected:
00080 virtual size_t DoPump(lword &byteCount, bool blockingOutput,
00081 unsigned long maxTime, bool checkDelimiter, byte delimiter) =0;
00082
00083 bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; }
00084
00085 private:
00086 bool m_messageEndSent, m_doPumpBlocked, m_blockedBySpeedLimit;
00087 };
00088
00089
00090 class CRYPTOPP_NO_VTABLE NetworkReceiver : public Waitable
00091 {
00092 public:
00093 virtual bool MustWaitToReceive() {return false;}
00094 virtual bool MustWaitForResult() {return false;}
00095
00096 virtual bool Receive(byte* buf, size_t bufLen) =0;
00097 virtual unsigned int GetReceiveResult() =0;
00098 virtual bool EofReceived() const =0;
00099 };
00100
00101 class CRYPTOPP_NO_VTABLE NonblockingSinkInfo
00102 {
00103 public:
00104 virtual ~NonblockingSinkInfo() {}
00105 virtual size_t GetMaxBufferSize() const =0;
00106 virtual size_t GetCurrentBufferSize() const =0;
00107 virtual bool EofPending() const =0;
00108
00109 virtual float ComputeCurrentSpeed() =0;
00110
00111 virtual float GetMaxObservedSpeed() const =0;
00112 };
00113
00114
00115 class CRYPTOPP_NO_VTABLE NonblockingSink : public Sink, public NonblockingSinkInfo, public LimitedBandwidth
00116 {
00117 public:
00118 NonblockingSink() : m_blockedBySpeedLimit(false) {}
00119
00120 bool IsolatedFlush(bool hardFlush, bool blocking);
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 lword TimedFlush(unsigned long maxTime, size_t targetSize = 0);
00133
00134 virtual void SetMaxBufferSize(size_t maxBufferSize) =0;
00135
00136 virtual void SetAutoFlushBound(size_t bound) =0;
00137
00138 protected:
00139 virtual lword DoFlush(unsigned long maxTime, size_t targetSize) = 0;
00140
00141 bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; }
00142
00143 private:
00144 bool m_blockedBySpeedLimit;
00145 };
00146
00147
00148 class CRYPTOPP_NO_VTABLE NetworkSender : public Waitable
00149 {
00150 public:
00151 virtual bool MustWaitToSend() {return false;}
00152 virtual bool MustWaitForResult() {return false;}
00153 virtual void Send(const byte* buf, size_t bufLen) =0;
00154 virtual unsigned int GetSendResult() =0;
00155 virtual bool MustWaitForEof() {return false;}
00156 virtual void SendEof() =0;
00157 virtual bool EofSent() {return false;}
00158 };
00159
00160 #ifdef HIGHRES_TIMER_AVAILABLE
00161
00162
00163 class CRYPTOPP_NO_VTABLE NetworkSource : public NonblockingSource
00164 {
00165 public:
00166 NetworkSource(BufferedTransformation *attachment);
00167
00168 unsigned int GetMaxWaitObjectCount() const;
00169 void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
00170
00171 bool SourceExhausted() const {return m_dataBegin == m_dataEnd && GetReceiver().EofReceived();}
00172
00173 protected:
00174 size_t DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter);
00175
00176 virtual NetworkReceiver & AccessReceiver() =0;
00177 const NetworkReceiver & GetReceiver() const {return const_cast<NetworkSource *>(this)->AccessReceiver();}
00178
00179 private:
00180 SecByteBlock m_buf;
00181 size_t m_putSize, m_dataBegin, m_dataEnd;
00182 bool m_waitingForResult, m_outputBlocked;
00183 };
00184
00185
00186 class CRYPTOPP_NO_VTABLE NetworkSink : public NonblockingSink
00187 {
00188 public:
00189 NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound);
00190
00191 unsigned int GetMaxWaitObjectCount() const;
00192 void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
00193
00194 size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
00195
00196 void SetMaxBufferSize(size_t maxBufferSize) {m_maxBufferSize = maxBufferSize; m_buffer.SetNodeSize(UnsignedMin(maxBufferSize, 16U*1024U+256U));}
00197 void SetAutoFlushBound(size_t bound) {m_autoFlushBound = bound;}
00198
00199 size_t GetMaxBufferSize() const {return m_maxBufferSize;}
00200 size_t GetCurrentBufferSize() const {return (size_t)m_buffer.CurrentSize();}
00201
00202 void ClearBuffer() { m_buffer.Clear(); }
00203
00204 bool EofPending() const { return m_eofState > EOF_NONE && m_eofState < EOF_DONE; }
00205
00206
00207 float ComputeCurrentSpeed();
00208
00209 float GetMaxObservedSpeed() const;
00210
00211 protected:
00212 lword DoFlush(unsigned long maxTime, size_t targetSize);
00213
00214 virtual NetworkSender & AccessSender() =0;
00215 const NetworkSender & GetSender() const {return const_cast<NetworkSink *>(this)->AccessSender();}
00216
00217 private:
00218 enum EofState { EOF_NONE, EOF_PENDING_SEND, EOF_PENDING_DELIVERY, EOF_DONE };
00219
00220 size_t m_maxBufferSize, m_autoFlushBound;
00221 bool m_needSendResult, m_wasBlocked;
00222 EofState m_eofState;
00223 ByteQueue m_buffer;
00224 size_t m_skipBytes;
00225 Timer m_speedTimer;
00226 float m_byteCountSinceLastTimerReset, m_currentSpeed, m_maxObservedSpeed;
00227 };
00228
00229 #endif // #ifdef HIGHRES_TIMER_AVAILABLE
00230
00231 NAMESPACE_END
00232
00233 #endif