- Main Page
- Namespaces
- Classes
- Files

# 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