void AsyncUDPSocket::handleRead() noexcept { void* buf{nullptr}; size_t len{0}; readCallback_->getReadBuffer(&buf, &len); if (buf == nullptr || len == 0) { AsyncSocketException ex( AsyncSocketException::BAD_ARGS, "AsyncUDPSocket::getReadBuffer() returned empty buffer"); auto cob = readCallback_; readCallback_ = nullptr; cob->onReadError(ex); updateRegistration(); return; } struct sockaddr_storage addrStorage; socklen_t addrLen = sizeof(addrStorage); memset(&addrStorage, 0, addrLen); struct sockaddr* rawAddr = reinterpret_cast<sockaddr*>(&addrStorage); rawAddr->sa_family = localAddress_.getFamily(); ssize_t bytesRead = recvfrom(fd_, buf, len, MSG_TRUNC, rawAddr, &addrLen); if (bytesRead >= 0) { clientAddress_.setFromSockaddr(rawAddr, addrLen); if (bytesRead > 0) { bool truncated = false; if ((size_t)bytesRead > len) { truncated = true; bytesRead = len; } readCallback_->onDataAvailable(clientAddress_, bytesRead, truncated); } } else { if (errno == EAGAIN || errno == EWOULDBLOCK) { // No data could be read without blocking the socket return; } AsyncSocketException ex(AsyncSocketException::INTERNAL_ERROR, "::recvfrom() failed", errno); // In case of UDP we can continue reading from the socket // even if the current request fails. We notify the user // so that he can do some logging/stats collection if he wants. auto cob = readCallback_; readCallback_ = nullptr; cob->onReadError(ex); updateRegistration(); } }
void DriverConnection::afterReadFormHeader(const boost::system::error_code& e) { // start timer nextContext_.serverTimer.restart(); if (!e) { if (nextContext_.sequence() == 0 || nextContext_.formPayloadSize() == 0) { // header size 0 indicates eof shutdownReceive(); } else if (nextContext_.formPayloadSize() > kLimitSize) { context_ptr context = createContext(); asyncWriteError(context, "Size exceeds limit."); shutdownReceive(); } else { // allocate enough space to receive payload nextContext_.formPayload.resize(nextContext_.formPayloadSize()); asyncReadFormPayload(); } } else { // sequence has not been read yet, set to 0 explicitly. nextContext_.setSequence(0); onReadError(e); } }
void DriverConnection::afterReadFormPayload( const boost::system::error_code& e ) { if (!e) { context_ptr context = createContext(); poller_.poll( boost::bind( &DriverConnection::handleRequest, shared_from_this(), context, boost::asio::placeholders::error ) ); // read next form asyncReadFormHeader(); } else { onReadError(e); } }
void AsyncUDPSocket::handleRead() noexcept { void *buf{nullptr}; size_t len{0}; struct msghdr *msg{nullptr}; readCallback_->getMessageHeader(&msg); if (msg == nullptr) { AsyncSocketException ex( AsyncSocketException::BAD_ARGS, "AsyncUDPSocket::getMessageHeader() returned empty header"); auto cob = readCallback_; readCallback_ = nullptr; cob->onReadError(ex); updateRegistration(); return; } ssize_t bytesRead = ::recvmsg(fd_, msg, MSG_DONTWAIT); if (bytesRead >= 0) { readCallback_->onMessageAvailable(bytesRead); } else { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { // No data could be read without blocking the socket return; } AsyncSocketException ex(AsyncSocketException::INTERNAL_ERROR, "::recvmsg() failed", errno); // In case of UDP we can continue reading from the socket // even if the current request fails. We notify the user // so that he can do some logging/stats collection if he wants. auto cob = readCallback_; readCallback_ = nullptr; cob->onReadError(ex); updateRegistration(); } }