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 Wed Jul 28 08:07:08 2004 for Crypto++ by doxygen 1.3.7