Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

network.cpp

00001 // network.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "network.h"
00005 
00006 NAMESPACE_BEGIN(CryptoPP)
00007 
00008 unsigned int NonblockingSource::PumpMessages2(unsigned int &messageCount, bool blocking)
00009 {
00010         if (messageCount == 0)
00011                 return 0;
00012 
00013         unsigned long byteCount = ULONG_MAX;
00014         messageCount = 0;
00015         RETURN_IF_NONZERO(Pump2(byteCount, blocking));
00016         if (!m_messageEndSent && SourceExhausted())
00017         {
00018                 RETURN_IF_NONZERO(AttachedTransformation()->Put2(NULL, 0, GetAutoSignalPropagation(), true));
00019                 m_messageEndSent = true;
00020                 messageCount = 1;
00021         }
00022         return 0;
00023 }
00024 
00025 bool NonblockingSink::IsolatedFlush(bool hardFlush, bool blocking)
00026 {
00027         TimedFlush(blocking ? INFINITE_TIME : 0);
00028         return hardFlush && !!GetCurrentBufferSize();
00029 }
00030 
00031 // *************************************************************
00032 
00033 #ifdef HIGHRES_TIMER_AVAILABLE
00034 
00035 NetworkSource::NetworkSource(BufferedTransformation *attachment)
00036         : NonblockingSource(attachment), m_buf(1024*4), m_bufSize(0), m_state(NORMAL)
00037 {
00038 }
00039 
00040 unsigned int NetworkSource::GeneralPump2(unsigned long &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter)
00041 {
00042         NetworkReceiver &receiver = AccessReceiver();
00043 
00044         unsigned long maxSize = byteCount;
00045         byteCount = 0;
00046         bool forever = maxTime == INFINITE_TIME;
00047         Timer timer(Timer::MILLISECONDS, forever);
00048         unsigned long timeout;
00049         BufferedTransformation *t = AttachedTransformation();
00050 
00051         if (m_state == OUTPUT_BLOCKED)
00052                 goto DoOutput;
00053 
00054         while (true)
00055         {
00056                 if (m_state == WAITING_FOR_RESULT)
00057                 {
00058                         if (receiver.MustWaitForResult())
00059                         {
00060                                 timeout = SaturatingSubtract(maxTime, timer.ElapsedTime());
00061                                 if (!receiver.Wait(timeout))
00062                                         break;
00063                         }
00064 
00065                         unsigned int recvResult = receiver.GetReceiveResult();
00066 //                      assert(recvResult > 0 || receiver.EofReceived());
00067                         m_bufSize += recvResult;
00068                         m_state = NORMAL;
00069                 }
00070 
00071                 if (m_bufSize == 0)
00072                 {
00073                         if (receiver.EofReceived())
00074                                 break;
00075                 }
00076                 else
00077                 {
00078                         m_putSize = STDMIN((unsigned long)m_bufSize, maxSize - byteCount);
00079                         if (checkDelimiter)
00080                                 m_putSize = std::find(m_buf.begin(), m_buf+m_putSize, delimiter) - m_buf;
00081 
00082 DoOutput:
00083                         unsigned int result = t->PutModifiable2(m_buf, m_putSize, 0, forever || blockingOutput);
00084                         if (result)
00085                         {
00086                                 timeout = SaturatingSubtract(maxTime, timer.ElapsedTime());
00087                                 if (t->Wait(timeout))
00088                                         goto DoOutput;
00089                                 else
00090                                 {
00091                                         m_state = OUTPUT_BLOCKED;
00092                                         return result;
00093                                 }
00094                         }
00095                         m_state = NORMAL;
00096 
00097                         byteCount += m_putSize;
00098                         m_bufSize -= m_putSize;
00099                         if (m_bufSize > 0)
00100                         {
00101                                 memmove(m_buf, m_buf+m_putSize, m_bufSize);
00102                                 if (checkDelimiter && m_buf[0] == delimiter)
00103                                         break;
00104                         }
00105                 }
00106 
00107                 if (byteCount == maxSize)
00108                         break;
00109 
00110                 unsigned long elapsed = timer.ElapsedTime();
00111                 if (elapsed > maxTime)
00112                         break;  // once time limit is reached, return even if there is more data waiting
00113 
00114                 if (receiver.MustWaitToReceive())
00115                 {
00116                         if (!receiver.Wait(maxTime - elapsed))
00117                                 break;
00118                 }
00119 
00120                 receiver.Receive(m_buf+m_bufSize, m_buf.size()-m_bufSize);
00121                 m_state = WAITING_FOR_RESULT;
00122         }
00123 
00124         return 0;
00125 }
00126 
00127 // *************************************************************
00128 
00129 unsigned int NetworkSink::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
00130 {
00131         if (m_blockedBytes)
00132         {
00133                 assert(length >= m_blockedBytes);
00134                 inString += length - m_blockedBytes;
00135                 length = m_blockedBytes;
00136         }
00137         m_buffer.LazyPut(inString, length);
00138 
00139         unsigned int targetSize = messageEnd ? 0 : m_maxBufferSize;
00140         TimedFlush(blocking ? INFINITE_TIME : 0, m_autoFlush ? 0 : targetSize);
00141 
00142         if (m_buffer.CurrentSize() > targetSize)
00143         {
00144                 assert(!blocking);
00145                 m_blockedBytes = STDMIN(m_buffer.CurrentSize() - targetSize, (unsigned long)length);
00146                 m_buffer.UndoLazyPut(m_blockedBytes);
00147                 m_buffer.FinalizeLazyPut();
00148                 return STDMAX(m_blockedBytes, 1U);
00149         }
00150         m_blockedBytes = 0;
00151 
00152         if (messageEnd)
00153                 AccessSender().SendEof();
00154         return 0;
00155 }
00156 
00157 unsigned int NetworkSink::TimedFlush(unsigned long maxTime, unsigned int targetSize)
00158 {
00159         if (m_buffer.IsEmpty())
00160                 return 0;
00161 
00162         NetworkSender &sender = AccessSender();
00163 
00164         bool forever = maxTime == INFINITE_TIME;
00165         Timer timer(Timer::MILLISECONDS, forever);
00166         unsigned long timeout;
00167         unsigned int totalFlushSize = 0;
00168 
00169         while (true)
00170         {
00171                 if (m_needSendResult)
00172                 {
00173                         if (sender.MustWaitForResult())
00174                         {
00175                                 timeout = SaturatingSubtract(maxTime, timer.ElapsedTime());
00176                                 if (!sender.Wait(timeout))
00177                                         break;
00178                         }
00179 
00180                         unsigned int sendResult = sender.GetSendResult();
00181                         m_buffer.Skip(sendResult);
00182                         totalFlushSize += sendResult;
00183                         m_needSendResult = false;
00184 
00185                         if (m_buffer.CurrentSize() <= targetSize)
00186                                 break;
00187                 }
00188 
00189                 unsigned long elapsed = timer.ElapsedTime();
00190                 if (elapsed > maxTime)
00191                         break;  // once time limit is reached, return even if there is more data waiting
00192 
00193                 if (sender.MustWaitToSend())
00194                 {
00195                         if (!sender.Wait(maxTime - elapsed))
00196                                 break;
00197                 }
00198 
00199                 unsigned int contiguousSize = 0;
00200                 const byte *block = m_buffer.Spy(contiguousSize);
00201 
00202                 sender.Send(block, contiguousSize);
00203                 m_needSendResult = true;
00204         }
00205 
00206         return totalFlushSize;
00207 }
00208 
00209 #endif  // #ifdef HIGHRES_TIMER_AVAILABLE
00210 
00211 NAMESPACE_END

Generated on Mon Apr 19 18:12:31 2004 for Crypto++ by doxygen 1.3.6-20040222