Crypto++
|
00001 #ifndef CRYPTOPP_NETWORK_H 00002 #define CRYPTOPP_NETWORK_H 00003 00004 #include "config.h" 00005 00006 #ifdef HIGHRES_TIMER_AVAILABLE 00007 00008 #include "filters.h" 00009 #include "hrtimer.h" 00010 00011 #include <deque> 00012 00013 NAMESPACE_BEGIN(CryptoPP) 00014 00015 class LimitedBandwidth 00016 { 00017 public: 00018 LimitedBandwidth(lword maxBytesPerSecond = 0) 00019 : m_maxBytesPerSecond(maxBytesPerSecond), m_timer(Timer::MILLISECONDS) 00020 , m_nextTransceiveTime(0) 00021 { m_timer.StartTimer(); } 00022 00023 lword GetMaxBytesPerSecond() const 00024 { return m_maxBytesPerSecond; } 00025 00026 void SetMaxBytesPerSecond(lword v) 00027 { m_maxBytesPerSecond = v; } 00028 00029 lword ComputeCurrentTransceiveLimit(); 00030 00031 double TimeToNextTransceive(); 00032 00033 void NoteTransceive(lword size); 00034 00035 public: 00036 /*! GetWaitObjects() must be called despite the 0 return from GetMaxWaitObjectCount(); 00037 the 0 is because the ScheduleEvent() method is used instead of adding a wait object */ 00038 unsigned int GetMaxWaitObjectCount() const { return 0; } 00039 void GetWaitObjects(WaitObjectContainer &container, const CallStack &callStack); 00040 00041 private: 00042 lword m_maxBytesPerSecond; 00043 00044 typedef std::deque<std::pair<double, lword> > OpQueue; 00045 OpQueue m_ops; 00046 00047 Timer m_timer; 00048 double m_nextTransceiveTime; 00049 00050 void ComputeNextTransceiveTime(); 00051 double GetCurTimeAndCleanUp(); 00052 }; 00053 00054 //! a Source class that can pump from a device for a specified amount of time. 00055 class CRYPTOPP_NO_VTABLE NonblockingSource : public AutoSignaling<Source>, public LimitedBandwidth 00056 { 00057 public: 00058 NonblockingSource(BufferedTransformation *attachment) 00059 : m_messageEndSent(false) , m_doPumpBlocked(false), m_blockedBySpeedLimit(false) {Detach(attachment);} 00060 00061 //! \name NONBLOCKING SOURCE 00062 //@{ 00063 00064 //! pump up to maxSize bytes using at most maxTime milliseconds 00065 /*! If checkDelimiter is true, pump up to delimiter, which itself is not extracted or pumped. */ 00066 size_t GeneralPump2(lword &byteCount, bool blockingOutput=true, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n'); 00067 00068 lword GeneralPump(lword maxSize=LWORD_MAX, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n') 00069 { 00070 GeneralPump2(maxSize, true, maxTime, checkDelimiter, delimiter); 00071 return maxSize; 00072 } 00073 lword TimedPump(unsigned long maxTime) 00074 {return GeneralPump(LWORD_MAX, maxTime);} 00075 lword PumpLine(byte delimiter='\n', lword maxSize=1024) 00076 {return GeneralPump(maxSize, INFINITE_TIME, true, delimiter);} 00077 00078 size_t Pump2(lword &byteCount, bool blocking=true) 00079 {return GeneralPump2(byteCount, blocking, blocking ? INFINITE_TIME : 0);} 00080 size_t PumpMessages2(unsigned int &messageCount, bool blocking=true); 00081 //@} 00082 00083 protected: 00084 virtual size_t DoPump(lword &byteCount, bool blockingOutput, 00085 unsigned long maxTime, bool checkDelimiter, byte delimiter) =0; 00086 00087 bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; } 00088 00089 private: 00090 bool m_messageEndSent, m_doPumpBlocked, m_blockedBySpeedLimit; 00091 }; 00092 00093 //! Network Receiver 00094 class CRYPTOPP_NO_VTABLE NetworkReceiver : public Waitable 00095 { 00096 public: 00097 virtual bool MustWaitToReceive() {return false;} 00098 virtual bool MustWaitForResult() {return false;} 00099 //! receive data from network source, returns whether result is immediately available 00100 virtual bool Receive(byte* buf, size_t bufLen) =0; 00101 virtual unsigned int GetReceiveResult() =0; 00102 virtual bool EofReceived() const =0; 00103 }; 00104 00105 class CRYPTOPP_NO_VTABLE NonblockingSinkInfo 00106 { 00107 public: 00108 virtual ~NonblockingSinkInfo() {} 00109 virtual size_t GetMaxBufferSize() const =0; 00110 virtual size_t GetCurrentBufferSize() const =0; 00111 virtual bool EofPending() const =0; 00112 //! compute the current speed of this sink in bytes per second 00113 virtual float ComputeCurrentSpeed() =0; 00114 //! get the maximum observed speed of this sink in bytes per second 00115 virtual float GetMaxObservedSpeed() const =0; 00116 }; 00117 00118 //! a Sink class that queues input and can flush to a device for a specified amount of time. 00119 class CRYPTOPP_NO_VTABLE NonblockingSink : public Sink, public NonblockingSinkInfo, public LimitedBandwidth 00120 { 00121 public: 00122 NonblockingSink() : m_blockedBySpeedLimit(false) {} 00123 00124 bool IsolatedFlush(bool hardFlush, bool blocking); 00125 00126 //! flush to device for no more than maxTime milliseconds 00127 /*! This function will repeatedly attempt to flush data to some device, until 00128 the queue is empty, or a total of maxTime milliseconds have elapsed. 00129 If maxTime == 0, at least one attempt will be made to flush some data, but 00130 it is likely that not all queued data will be flushed, even if the device 00131 is ready to receive more data without waiting. If you want to flush as much data 00132 as possible without waiting for the device, call this function in a loop. 00133 For example: while (sink.TimedFlush(0) > 0) {} 00134 \return number of bytes flushed 00135 */ 00136 lword TimedFlush(unsigned long maxTime, size_t targetSize = 0); 00137 00138 virtual void SetMaxBufferSize(size_t maxBufferSize) =0; 00139 //! set a bound which will cause sink to flush if exceeded by GetCurrentBufferSize() 00140 virtual void SetAutoFlushBound(size_t bound) =0; 00141 00142 protected: 00143 virtual lword DoFlush(unsigned long maxTime, size_t targetSize) = 0; 00144 00145 bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; } 00146 00147 private: 00148 bool m_blockedBySpeedLimit; 00149 }; 00150 00151 //! Network Sender 00152 class CRYPTOPP_NO_VTABLE NetworkSender : public Waitable 00153 { 00154 public: 00155 virtual bool MustWaitToSend() {return false;} 00156 virtual bool MustWaitForResult() {return false;} 00157 virtual void Send(const byte* buf, size_t bufLen) =0; 00158 virtual unsigned int GetSendResult() =0; 00159 virtual bool MustWaitForEof() {return false;} 00160 virtual void SendEof() =0; 00161 virtual bool EofSent() {return false;} // implement if MustWaitForEof() == true 00162 }; 00163 00164 //! Network Source 00165 class CRYPTOPP_NO_VTABLE NetworkSource : public NonblockingSource 00166 { 00167 public: 00168 NetworkSource(BufferedTransformation *attachment); 00169 00170 unsigned int GetMaxWaitObjectCount() const; 00171 void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack); 00172 00173 bool SourceExhausted() const {return m_dataBegin == m_dataEnd && GetReceiver().EofReceived();} 00174 00175 protected: 00176 size_t DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter); 00177 00178 virtual NetworkReceiver & AccessReceiver() =0; 00179 const NetworkReceiver & GetReceiver() const {return const_cast<NetworkSource *>(this)->AccessReceiver();} 00180 00181 private: 00182 SecByteBlock m_buf; 00183 size_t m_putSize, m_dataBegin, m_dataEnd; 00184 bool m_waitingForResult, m_outputBlocked; 00185 }; 00186 00187 //! Network Sink 00188 class CRYPTOPP_NO_VTABLE NetworkSink : public NonblockingSink 00189 { 00190 public: 00191 NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound); 00192 00193 unsigned int GetMaxWaitObjectCount() const; 00194 void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack); 00195 00196 size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); 00197 00198 void SetMaxBufferSize(size_t maxBufferSize) {m_maxBufferSize = maxBufferSize; m_buffer.SetNodeSize(UnsignedMin(maxBufferSize, 16U*1024U+256U));} 00199 void SetAutoFlushBound(size_t bound) {m_autoFlushBound = bound;} 00200 00201 size_t GetMaxBufferSize() const {return m_maxBufferSize;} 00202 size_t GetCurrentBufferSize() const {return (size_t)m_buffer.CurrentSize();} 00203 00204 void ClearBuffer() { m_buffer.Clear(); } 00205 00206 bool EofPending() const { return m_eofState > EOF_NONE && m_eofState < EOF_DONE; } 00207 00208 //! compute the current speed of this sink in bytes per second 00209 float ComputeCurrentSpeed(); 00210 //! get the maximum observed speed of this sink in bytes per second 00211 float GetMaxObservedSpeed() const; 00212 00213 protected: 00214 lword DoFlush(unsigned long maxTime, size_t targetSize); 00215 00216 virtual NetworkSender & AccessSender() =0; 00217 const NetworkSender & GetSender() const {return const_cast<NetworkSink *>(this)->AccessSender();} 00218 00219 private: 00220 enum EofState { EOF_NONE, EOF_PENDING_SEND, EOF_PENDING_DELIVERY, EOF_DONE }; 00221 00222 size_t m_maxBufferSize, m_autoFlushBound; 00223 bool m_needSendResult, m_wasBlocked; 00224 EofState m_eofState; 00225 ByteQueue m_buffer; 00226 size_t m_skipBytes; 00227 Timer m_speedTimer; 00228 float m_byteCountSinceLastTimerReset, m_currentSpeed, m_maxObservedSpeed; 00229 }; 00230 00231 NAMESPACE_END 00232 00233 #endif // #ifdef HIGHRES_TIMER_AVAILABLE 00234 00235 #endif