- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# 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