Crypto++

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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