void AsyncPipeWriter::handleWrite() { DestructorGuard dg(this); assert(!queue_.empty()); do { auto& front = queue_.front(); folly::IOBufQueue& curQueue = front.first; DCHECK(!curQueue.empty()); // someday, support writev. The logic for partial writes is a bit complex const IOBuf* head = curQueue.front(); CHECK(head->length()); #if _WIN32 // On Windows you can't call write on a socket. ssize_t rc = folly::fileutil_detail::wrapNoInt( send_internal, fd_, head->data(), head->length()); #else ssize_t rc = folly::writeNoInt(fd_.toFd(), head->data(), head->length()); #endif if (rc < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // pipe is full VLOG(5) << "write blocked"; registerHandler(EventHandler::WRITE); return; } else { failAllWrites(AsyncSocketException( AsyncSocketException::INTERNAL_ERROR, "write failed", errno)); closeNow(); return; } } else if (rc == 0) { registerHandler(EventHandler::WRITE); return; } curQueue.trimStart(size_t(rc)); if (curQueue.empty()) { auto cb = front.second; queue_.pop_front(); if (cb) { cb->writeSuccess(); } } else { VLOG(5) << "partial write blocked"; } } while (!queue_.empty()); if (closeOnEmpty_) { closeNow(); } else { unregisterHandler(); } }
void AsyncPipeWriter::closeOnEmpty() { VLOG(5) << "close on empty"; if (queue_.empty()) { closeNow(); } else { closeOnEmpty_ = true; CHECK(isHandlerRegistered()); } }
void DccTransferRecvWriteCacheHandler::slotKIOResult( KIO::Job* job ) { Q_ASSERT( m_transferJob ); disconnect( m_transferJob, 0, 0, 0 ); m_transferJob = 0; if ( job->error() ) { QString errorString = job->errorString(); closeNow(); emit gotError( errorString ); // -> DccTransferRecv::slotLocalGotWriteError() } }
void Cpp2Channel::destroy() { closeNow(); MessageChannel::destroy(); }
~ALSADevice() { closeNow(); }
void HTTPClientChannel::destroy() { closeNow(); folly::DelayedDestruction::destroy(); }
void Cpp2Channel::readDataAvailable(size_t len) noexcept { assert(recvCallback_); assert(len > 0); DestructorGuard dg(this); queue_->postallocate(len); if (recvCallback_ && recvCallback_->shouldSample() && !sample_) { sample_.reset(new RecvCallback::sample); sample_->readBegin = Util::currentTimeUsec(); } // Remaining for this packet. Will update the class member // variable below for the next call to getReadBuffer size_t remaining = 0; // Loop as long as there are complete (decrypted and deframed) frames. // Partial frames are stored inside the handlers between calls to // readDataAvailable. // On the last iteration, remaining_ is updated to the anticipated remaining // frame length (if we're in the middle of a frame) or to readBufferSize_ // (if we are exactly between frames) while (true) { unique_ptr<IOBuf> unframed; auto ex = folly::try_and_catch<std::exception>([&]() { IOBufQueue* decrypted; size_t rem = 0; std::tie(decrypted, rem) = protectionHandler_->decrypt(queue_.get()); if (!decrypted) { // no full message available, remember how many more bytes we need // and continue to frame decoding (because frame decoder might have // cached messages) remaining = rem; } // message decrypted std::tie(unframed, rem) = framingHandler_->removeFrame(decrypted); if (!unframed && remaining == 0) { // no full message available, update remaining but only if previous // handler (encryption) hasn't already provided a value remaining = rem; } }); if (ex) { if (recvCallback_) { VLOG(5) << "Failed to read a message header"; recvCallback_->messageReceiveErrorWrapped(std::move(ex)); } else { LOG(ERROR) << "Failed to read a message header"; } closeNow(); return; } if (!unframed) { // no more data remaining_ = remaining > 0 ? remaining : readBufferSize_; return; } if (!recvCallback_) { LOG(ERROR) << "Received a message, but no recvCallback_ installed!"; continue; } if (sample_) { sample_->readEnd = Util::currentTimeUsec(); } recvCallback_->messageReceived(std::move(unframed), std::move(sample_)); if (closing_) { return; // don't call more callbacks if we are going to be destroyed } } }
void Cpp2Channel::readDataAvailable(size_t len) noexcept { assert(recvCallback_); assert(len > 0); DestructorGuard dg(this); queue_->postallocate(len); if (recvCallback_ && recvCallback_->shouldSample() && !sample_) { sample_.reset(new RecvCallback::sample); sample_->readBegin = Util::currentTimeUsec(); } // Remaining for this packet. Will update the class member // variable below for the next call to getReadBuffer size_t remaining = 0; while (true) { unique_ptr<IOBuf> unframed; try { if (protectionState_ == ProtectionState::INVALID) { throw TTransportException("protection state is invalid"); } // If we have a full frame already in a queue ready to go, use // it. if (protectionState_ != ProtectionState::VALID && queue_->front()) { unframed = removeFrame(queue_.get(), remaining); } else if (protectionState_ == ProtectionState::VALID && pendingPlaintext_->front()) { unframed = removeFrame(pendingPlaintext_.get(), remaining); } // We should either get a buffer back, or a remaining indicator. // Never both. Neither is possible, if the length of the framed // data is zero. assert(!(unframed && remaining > 0)); // If there wasn't a full message available and we have a // protection layer, attempt to unwrap the next piece of // ciphertext. if (!unframed && protectionState_ == ProtectionState::VALID && queue_->front()) { assert(saslEndpoint_ != NULL); unique_ptr<IOBuf> unwrapped = saslEndpoint_->unwrap(queue_.get(), &remaining); assert(!(unwrapped && remaining > 0)); if (unwrapped) { pendingPlaintext_->append(std::move(unwrapped)); // Start again from the top. continue; } } } catch (const std::exception& e) { if (recvCallback_) { VLOG(5) << "Failed to read a message header"; recvCallback_->messageReceiveError(std::current_exception()); } else { LOG(ERROR) << "Failed to read a message header"; } closeNow(); return; } if (remaining > 0) { this->remaining_ = remaining; return; } if (!unframed) { break; } if (!recvCallback_) { LOG(ERROR) << "Received a message, but no recvCallback_ installed!"; continue; } if (sample_) { sample_->readEnd = Util::currentTimeUsec(); } recvCallback_->messageReceived(std::move(unframed), std::move(sample_)); if (closing_) { return; // don't call more callbacks if we are going to be destroyed } } this->remaining_ = 2048; }
DccTransferRecvWriteCacheHandler::~DccTransferRecvWriteCacheHandler() { closeNow(); }
void MockMcClientTransport::close() { closeNow(); }