network.h

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

Generated on Sat Dec 23 02:07:08 2006 for Crypto++ by  doxygen 1.5.1-p1