network.h

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         /*! GetWaitObjects() must be called despite the 0 return from GetMaxWaitObjectCount();
00033             the 0 is because the ScheduleEvent() method is used instead of adding a wait object */
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 //! a Source class that can pump from a device for a specified amount of time.
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         //!     \name NONBLOCKING SOURCE
00058         //@{
00059 
00060         //! pump up to maxSize bytes using at most maxTime milliseconds
00061         /*! If checkDelimiter is true, pump up to delimiter, which itself is not extracted or pumped. */
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 //! Network Receiver
00090 class CRYPTOPP_NO_VTABLE NetworkReceiver : public Waitable
00091 {
00092 public:
00093         virtual bool MustWaitToReceive() {return false;}
00094         virtual bool MustWaitForResult() {return false;}
00095         //! receive data from network source, returns whether result is immediately available
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         //! compute the current speed of this sink in bytes per second
00109         virtual float ComputeCurrentSpeed() =0;
00110         //! get the maximum observed speed of this sink in bytes per second
00111         virtual float GetMaxObservedSpeed() const =0;
00112 };
00113 
00114 //! a Sink class that queues input and can flush to a device for a specified amount of time.
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         //! flush to device for no more than maxTime milliseconds
00123         /*! This function will repeatedly attempt to flush data to some device, until
00124                 the queue is empty, or a total of maxTime milliseconds have elapsed.
00125                 If maxTime == 0, at least one attempt will be made to flush some data, but
00126                 it is likely that not all queued data will be flushed, even if the device
00127                 is ready to receive more data without waiting. If you want to flush as much data
00128                 as possible without waiting for the device, call this function in a loop.
00129                 For example: while (sink.TimedFlush(0) > 0) {}
00130                 \return number of bytes flushed
00131         */
00132         lword TimedFlush(unsigned long maxTime, size_t targetSize = 0);
00133 
00134         virtual void SetMaxBufferSize(size_t maxBufferSize) =0;
00135         //! set a bound which will cause sink to flush if exceeded by GetCurrentBufferSize()
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 //! Network Sender
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;}  // implement if MustWaitForEof() == true
00158 };
00159 
00160 #ifdef HIGHRES_TIMER_AVAILABLE
00161 
00162 //! Network Source
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 //! Network Sink
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         //! compute the current speed of this sink in bytes per second
00207         float ComputeCurrentSpeed();
00208         //! get the maximum observed speed of this sink in bytes per second
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

Generated on Thu Nov 23 15:57:42 2006 for Crypto++ by  doxygen 1.5.1-p1