Beispiel #1
0
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);
    }
}
Beispiel #4
0
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();
  }
}