void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) { if (m_resultPending) container.AddHandle(m_event, CallStack("SocketReceiver::GetWaitObjects() - result pending", &callStack)); else if (!m_eofReceived) container.SetNoWait(CallStack("SocketReceiver::GetWaitObjects() - result ready", &callStack)); }
void WindowsPipeSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) { if (m_resultPending) container.AddHandle(m_event, CallStack("WindowsPipeSender::GetWaitObjects() - result pending", &callStack)); else container.SetNoWait(CallStack("WindowsPipeSender::GetWaitObjects() - result ready", &callStack)); }
void NetworkSink::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) { if (BlockedBySpeedLimit()) LimitedBandwidth::GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - speed limit", &callStack)); else if (m_wasBlocked) AccessSender().GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - was blocked", &callStack)); else if (!m_buffer.IsEmpty()) AccessSender().GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - buffer not empty", &callStack)); else if (EofPending()) AccessSender().GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - EOF pending", &callStack)); }
void NetworkSource::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) { if (BlockedBySpeedLimit()) LimitedBandwidth::GetWaitObjects(container, CallStack("NetworkSource::GetWaitObjects() - speed limit", &callStack)); else if (!m_outputBlocked) { if (m_dataBegin == m_dataEnd) AccessReceiver().GetWaitObjects(container, CallStack("NetworkSource::GetWaitObjects() - no data", &callStack)); else container.SetNoWait(CallStack("NetworkSource::GetWaitObjects() - have data", &callStack)); } AttachedTransformation()->GetWaitObjects(container, CallStack("NetworkSource::GetWaitObjects() - attachment", &callStack)); }
void WaitObjectContainer::ScheduleEvent(double milliseconds, CallStack const& callStack) { if (milliseconds <= 3) DetectNoWait(LASTRESULT_SCHEDULED, CallStack("WaitObjectContainer::ScheduleEvent()", &callStack)); double thisEventTime = m_eventTimer.ElapsedTimeAsDouble() + milliseconds; if (!m_firstEventTime || thisEventTime < m_firstEventTime) m_firstEventTime = thisEventTime; }
lword NonblockingSink::TimedFlush(unsigned long maxTime, size_t targetSize) { m_blockedBySpeedLimit = false; size_t curBufSize = GetCurrentBufferSize(); if (curBufSize <= targetSize && (targetSize || !EofPending())) return 0; if (!GetMaxBytesPerSecond()) return DoFlush(maxTime, targetSize); bool forever = (maxTime == INFINITE_TIME); unsigned long timeToGo = maxTime; Timer timer(Timer::MILLISECONDS, forever); lword totalFlushed = 0; timer.StartTimer(); while (true) { size_t flushSize = UnsignedMin(curBufSize - targetSize, ComputeCurrentTransceiveLimit()); if (flushSize || EofPending()) { if (!forever) timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime()); size_t ret = (size_t)DoFlush(timeToGo, curBufSize - flushSize); if (ret) { NoteTransceive(ret); curBufSize -= ret; totalFlushed += ret; } } if (curBufSize <= targetSize && (targetSize || !EofPending())) break; if (!forever) { timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime()); if (!timeToGo) break; } double waitTime = TimeToNextTransceive(); if (!forever && waitTime > timeToGo) { m_blockedBySpeedLimit = true; break; } WaitObjectContainer container; LimitedBandwidth::GetWaitObjects(container, CallStack("NonblockingSink::TimedFlush() - speed limit", 0)); container.Wait((unsigned long)waitTime); } return totalFlushed; }
// // Debug implementation of Mutex void Mutex::Lock() { CallStack callContext = CallStack(); CheckAcquire(callContext); PR_Lock(mLock); Acquire(callContext); // protected by mLock }
// // Debug implementation of Monitor void Monitor::Enter() { BlockingResourceBase* chainFront = ResourceChainFront(); // the code below implements monitor reentrancy semantics if (this == chainFront) { // immediately re-entered the monitor: acceptable PR_EnterMonitor(mMonitor); ++mEntryCount; return; } CallStack callContext = CallStack(); // this is sort of a hack around not recording the thread that // owns this monitor if (chainFront) { for (BlockingResourceBase* br = ResourceChainPrev(chainFront); br; br = ResourceChainPrev(br)) { if (br == this) { NS_WARNING( "Re-entering Monitor after acquiring other resources.\n" "At calling context\n"); GetAcquisitionContext().Print(stderr); // show the caller why this is potentially bad CheckAcquire(callContext); PR_EnterMonitor(mMonitor); ++mEntryCount; return; } } } CheckAcquire(callContext); PR_EnterMonitor(mMonitor); NS_ASSERTION(0 == mEntryCount, "Monitor isn't free!"); Acquire(callContext); // protected by mMonitor mEntryCount = 1; }
lword NetworkSink::DoFlush(unsigned long maxTime, size_t targetSize) { NetworkSender &sender = AccessSender(); bool forever = maxTime == INFINITE_TIME; Timer timer(Timer::MILLISECONDS, forever); unsigned int totalFlushSize = 0; while (true) { if (m_buffer.CurrentSize() <= targetSize) break; if (m_needSendResult) { if (sender.MustWaitForResult() && !sender.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()), CallStack("NetworkSink::DoFlush() - wait send result", 0))) break; unsigned int sendResult = sender.GetSendResult(); #if CRYPTOPP_TRACE_NETWORK OutputDebugString((IntToString((unsigned int)this) + ": Sent " + IntToString(sendResult) + " bytes\n").c_str()); #endif m_buffer.Skip(sendResult); totalFlushSize += sendResult; m_needSendResult = false; if (!m_buffer.AnyRetrievable()) break; } unsigned long timeOut = maxTime ? SaturatingSubtract(maxTime, timer.ElapsedTime()) : 0; if (sender.MustWaitToSend() && !sender.Wait(timeOut, CallStack("NetworkSink::DoFlush() - wait send", 0))) break; size_t contiguousSize = 0; const byte *block = m_buffer.Spy(contiguousSize); #if CRYPTOPP_TRACE_NETWORK OutputDebugString((IntToString((unsigned int)this) + ": Sending " + IntToString(contiguousSize) + " bytes\n").c_str()); #endif sender.Send(block, contiguousSize); m_needSendResult = true; if (maxTime > 0 && timeOut == 0) break; // once time limit is reached, return even if there is more data waiting } m_byteCountSinceLastTimerReset += totalFlushSize; ComputeCurrentSpeed(); if (m_buffer.IsEmpty() && !m_needSendResult) { if (m_eofState == EOF_PENDING_SEND) { sender.SendEof(); m_eofState = sender.MustWaitForEof() ? EOF_PENDING_DELIVERY : EOF_DONE; } while (m_eofState == EOF_PENDING_DELIVERY) { unsigned long timeOut = maxTime ? SaturatingSubtract(maxTime, timer.ElapsedTime()) : 0; if (!sender.Wait(timeOut, CallStack("NetworkSink::DoFlush() - wait EOF", 0))) break; if (sender.EofSent()) m_eofState = EOF_DONE; } } return totalFlushSize; }
size_t NetworkSource::DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter) { NetworkReceiver &receiver = AccessReceiver(); lword maxSize = byteCount; byteCount = 0; bool forever = maxTime == INFINITE_TIME; Timer timer(Timer::MILLISECONDS, forever); BufferedTransformation *t = AttachedTransformation(); if (m_outputBlocked) goto DoOutput; while (true) { if (m_dataBegin == m_dataEnd) { if (receiver.EofReceived()) break; if (m_waitingForResult) { if (receiver.MustWaitForResult() && !receiver.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()), CallStack("NetworkSource::DoPump() - wait receive result", 0))) break; unsigned int recvResult = receiver.GetReceiveResult(); #if CRYPTOPP_TRACE_NETWORK OutputDebugString((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str()); #endif m_dataEnd += recvResult; m_waitingForResult = false; if (!receiver.MustWaitToReceive() && !receiver.EofReceived() && m_dataEnd != m_buf.size()) goto ReceiveNoWait; } else { m_dataEnd = m_dataBegin = 0; if (receiver.MustWaitToReceive()) { if (!receiver.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()), CallStack("NetworkSource::DoPump() - wait receive", 0))) break; receiver.Receive(m_buf+m_dataEnd, m_buf.size()-m_dataEnd); m_waitingForResult = true; } else { ReceiveNoWait: m_waitingForResult = true; // call Receive repeatedly as long as data is immediately available, // because some receivers tend to return data in small pieces #if CRYPTOPP_TRACE_NETWORK OutputDebugString((IntToString((unsigned int)this) + ": Receiving " + IntToString(m_buf.size()-m_dataEnd) + " bytes\n").c_str()); #endif while (receiver.Receive(m_buf+m_dataEnd, m_buf.size()-m_dataEnd)) { unsigned int recvResult = receiver.GetReceiveResult(); #if CRYPTOPP_TRACE_NETWORK OutputDebugString((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str()); #endif m_dataEnd += recvResult; if (receiver.EofReceived() || m_dataEnd > m_buf.size() /2) { m_waitingForResult = false; break; } } } } } else { m_putSize = UnsignedMin(m_dataEnd - m_dataBegin, maxSize - byteCount); if (checkDelimiter) m_putSize = std::find(m_buf+m_dataBegin, m_buf+m_dataBegin+m_putSize, delimiter) - (m_buf+m_dataBegin); DoOutput: size_t result = t->PutModifiable2(m_buf+m_dataBegin, m_putSize, 0, forever || blockingOutput); if (result) { if (t->Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()), CallStack("NetworkSource::DoPump() - wait attachment", 0))) goto DoOutput; else { m_outputBlocked = true; return result; } } m_outputBlocked = false; byteCount += m_putSize; m_dataBegin += m_putSize; if (checkDelimiter && m_dataBegin < m_dataEnd && m_buf[m_dataBegin] == delimiter) break; if (maxSize != ULONG_MAX && byteCount == maxSize) break; // once time limit is reached, return even if there is more data waiting // but make 0 a special case so caller can request a large amount of data to be // pumped as long as it is immediately available if (maxTime > 0 && timer.ElapsedTime() > maxTime) break; } } return 0; }
DWORD WINAPI Sampler::AsyncUpdate(LPVOID lpParam) { Sampler& sampler = *(Sampler*)(lpParam); std::vector<std::pair<HANDLE, ThreadEntry*>> openThreads; openThreads.reserve(sampler.targetThreads.size()); for (auto entryIterator = sampler.targetThreads.begin() ; entryIterator != sampler.targetThreads.end() ; ++entryIterator) { ThreadEntry* entry = *entryIterator; DWORD threadID = entry->description.threadID; BRO_VERIFY(threadID != GetCurrentThreadId(), "It's a bad idea to sample specified thread! Deadlock will occur!", continue); HANDLE hThread = GetThreadHandleByThreadID(threadID); if (hThread == 0) continue; openThreads.push_back(std::make_pair(hThread, entry)); } if (openThreads.empty()) return 0; CallStackBuffer buffer; CONTEXT context; while ( sampler.finishEvent.WaitForEvent(sampler.intervalMicroSeconds) ) { // Check whether we are inside sampling scope for (auto entry = openThreads.cbegin() ; entry != openThreads.cend() ; ++entry) { HANDLE handle = entry->first; const ThreadEntry* thread = entry->second; if (!thread->storage.isSampling) continue; uint count = 0; if (PauseThread(handle)) { // Check scope again because it is possible to leave sampling scope while trying to suspend main thread if (thread->storage.isSampling && RetrieveThreadContext(handle, context)) { count = sampler.symEngine.GetCallstack(handle, context, buffer); } ContinueThread(handle); } if (count > 0) { sampler.callstacks.push_back(CallStack(buffer.begin(), buffer.begin() + count)); } } } for (auto entry = openThreads.begin() ; entry != openThreads.end() ; ++entry) ReleaseThreadHandle(entry->first); return 0; }
void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) { container.AddWriteFd(m_s, CallStack("SocketSender::GetWaitObjects()", &callStack)); }
void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) { if (!m_eofReceived) container.AddReadFd(m_s, CallStack("SocketReceiver::GetWaitObjects()", &callStack)); }
void WaitObjectContainer::SetNoWait(CallStack const& callStack) { DetectNoWait(LASTRESULT_NOWAIT, CallStack("WaitObjectContainer::SetNoWait()", &callStack)); m_noWait = true; }
void WaitObjectContainer::AddHandle(HANDLE handle, CallStack const& callStack) { DetectNoWait(m_handles.size(), CallStack("WaitObjectContainer::AddHandle()", &callStack)); m_handles.push_back(handle); }
void LimitedBandwidth::GetWaitObjects(WaitObjectContainer &container, const CallStack &callStack) { double nextTransceiveTime = TimeToNextTransceive(); if (nextTransceiveTime) container.ScheduleEvent(nextTransceiveTime, CallStack("LimitedBandwidth::GetWaitObjects()", &callStack)); }
size_t NonblockingSource::GeneralPump2( lword& byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter) { m_blockedBySpeedLimit = false; if (!GetMaxBytesPerSecond()) { size_t ret = DoPump(byteCount, blockingOutput, maxTime, checkDelimiter, delimiter); m_doPumpBlocked = (ret != 0); return ret; } bool forever = (maxTime == INFINITE_TIME); unsigned long timeToGo = maxTime; Timer timer(Timer::MILLISECONDS, forever); lword maxSize = byteCount; byteCount = 0; timer.StartTimer(); while (true) { lword curMaxSize = UnsignedMin(ComputeCurrentTransceiveLimit(), maxSize - byteCount); if (curMaxSize || m_doPumpBlocked) { if (!forever) timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime()); size_t ret = DoPump(curMaxSize, blockingOutput, timeToGo, checkDelimiter, delimiter); m_doPumpBlocked = (ret != 0); if (curMaxSize) { NoteTransceive(curMaxSize); byteCount += curMaxSize; } if (ret) return ret; } if (maxSize != ULONG_MAX && byteCount >= maxSize) break; if (!forever) { timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime()); if (!timeToGo) break; } double waitTime = TimeToNextTransceive(); if (!forever && waitTime > timeToGo) { m_blockedBySpeedLimit = true; break; } WaitObjectContainer container; LimitedBandwidth::GetWaitObjects(container, CallStack("NonblockingSource::GeneralPump2() - speed limit", 0)); container.Wait((unsigned long)waitTime); } return 0; }
void ForwardTcpPort(const char *sourcePortName, const char *destinationHost, const char *destinationPortName) { #ifdef SOCKETS_AVAILABLE SocketsInitializer sockInit; Socket sockListen, sockSource, sockDestination; int sourcePort = Socket::PortNameToNumber(sourcePortName); int destinationPort = Socket::PortNameToNumber(destinationPortName); sockListen.Create(); sockListen.Bind(sourcePort); setsockopt(sockListen, IPPROTO_TCP, TCP_NODELAY, "\x01", 1); cout << "Listing on port " << sourcePort << ".\n"; sockListen.Listen(); sockListen.Accept(sockSource); cout << "Connection accepted on port " << sourcePort << ".\n"; sockListen.CloseSocket(); cout << "Making connection to " << destinationHost << ", port " << destinationPort << ".\n"; sockDestination.Create(); sockDestination.Connect(destinationHost, destinationPort); cout << "Connection made to " << destinationHost << ", starting to forward.\n"; SocketSource out(sockSource, false, new SocketSink(sockDestination)); SocketSource in(sockDestination, false, new SocketSink(sockSource)); WaitObjectContainer waitObjects; while (!(in.SourceExhausted() && out.SourceExhausted())) { waitObjects.Clear(); out.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - out", NULL)); in.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - in", NULL)); waitObjects.Wait(INFINITE_TIME); if (!out.SourceExhausted()) { cout << "o" << flush; out.PumpAll2(false); if (out.SourceExhausted()) cout << "EOF received on source socket.\n"; } if (!in.SourceExhausted()) { cout << "i" << flush; in.PumpAll2(false); if (in.SourceExhausted()) cout << "EOF received on destination socket.\n"; } } #else cout << "Socket support was not enabled at compile time.\n"; exit(-1); #endif }