Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Acceptor #216

Open
SteveSelva opened this issue Jun 2, 2023 · 0 comments
Open

Acceptor #216

SteveSelva opened this issue Jun 2, 2023 · 0 comments

Comments

@SteveSelva
Copy link

In wangle/server/Acceptor.cpp, for SSL Connections, the Handshake is done by Fizz. Since I needed a callback at ClientHello message to fetch the server name from SNI extension in ClientHello, I implemented the handshake using folly::AsyncSSLSocket which has the ClientHello callback function. Does this cause any issues in the functioning of Server?

Example.cpp (My Implementation)

void Example::onNewConnection(
        folly::AsyncTransport::UniquePtr sock,
        const SocketAddress* address,
        const std::string& nextProtocolName,
        SecureTransportType secureTransportType,
        const wangle::TransportInfo& tinfo) {
        LOG(INFO) << "Accepting Connection from Browser";
        auto& filter = serverOptions_.newConnectionFilter;
        if (filter) {
            try {
                filter(sock.get(), address, nextProtocolName, secureTransportType, tinfo);
            }
            catch (const std::exception& e) {
                sock->closeWithReset();
                LOG(INFO) << "Exception filtering new socket: " << folly::exceptionStr(e);
                return;
            }
        }
        LOG(INFO) <<"Security Protocol : "<< sock->getSecurityProtocol();

        HTTPSessionAcceptor::onNewConnection(std::move(sock), address, nextProtocolName, secureTransportType, tinfo);
    }


void Example::processEstablishedConnection(int fd, const folly::SocketAddress& clientAddr, std::chrono::steady_clock::time_point acceptTime, wangle::TransportInfo& tinfo) noexcept {
        if(!isSSL)
        {
            LOG(INFO) << "HTTP Connection";
            tinfo.secure = false;
            tinfo.acceptTime = acceptTime;
            folly::AsyncSocket::UniquePtr sock(makeNewAsyncSocket(base_, fd, &clientAddr));
            tinfo.tfoSucceded = sock->getTFOSucceded();
            plaintextConnectionReady(std::move(sock), clientAddr, tinfo);
        }
        else {
            LOG(INFO) << "HTTPS Connection";
            folly::EventBase* evb = getEventBase(); 
            folly::NetworkSocket ns = folly::NetworkSocket::fromFd(fd);
            this->getSSLContextManager()->getDefaultSSLCtx()->addClientHelloCallback(clientHelloCallback);
            folly::AsyncSSLSocket::UniquePtr sslSock(new folly::AsyncSSLSocket(this->getSSLContextManager()->getDefaultSSLCtx(), evb, ns, true, false, &clientAddr));
            sslSock->setSupportedApplicationProtocols({ "h2", "http/1.1"});
            sslSock->enableClientHelloParsing();
            sslSock->sslAccept(new HandshakeCB(), std::chrono::minutes(1), folly::SSLContext::SSLVerifyPeerEnum::USE_CTX);
            Example::onNewConnection(std::move(sslSock), &clientAddr, {}, wangle::SecureTransportType::TLS, tinfo);
        }
    }

Acceptor.cpp (Wangle's Implementation)

void Acceptor::processEstablishedConnection(
    int fd,
    const SocketAddress& clientAddr,
    std::chrono::steady_clock::time_point acceptTime,
    TransportInfo& tinfo) noexcept {
  bool shouldDoSSL = false;
  if (accConfig_.isSSL()) {
    CHECK(sslCtxManager_);
    shouldDoSSL = sslCtxManager_->getDefaultSSLCtx() != nullptr;
  }
  if (shouldDoSSL) {
    AsyncSSLSocket::UniquePtr sslSock(makeNewAsyncSSLSocket(
        sslCtxManager_->getDefaultSSLCtx(), base_, fd, &clientAddr));
    ++numPendingSSLConns_;
    if (numPendingSSLConns_ > accConfig_.maxConcurrentSSLHandshakes) {
      VLOG(2) << "dropped SSL handshake on " << accConfig_.name
              << " too many handshakes in progress";
      auto error = SSLErrorEnum::DROPPED;
      auto latency = std::chrono::milliseconds(0);
      auto ex = folly::make_exception_wrapper<SSLException>(
          error, latency, sslSock->getRawBytesReceived());
      updateSSLStats(sslSock.get(), latency, error, ex);
      sslConnectionError(ex);
      return;
    }

    tinfo.tfoSucceded = sslSock->getTFOSucceded();
    for (const auto& cb : observerList_.getAll()) {
      cb->accept(sslSock.get());
    }
    startHandshakeManager(
        std::move(sslSock), this, clientAddr, acceptTime, tinfo);
  } else {
    tinfo.secure = false;
    tinfo.acceptTime = acceptTime;
    AsyncSocket::UniquePtr sock(makeNewAsyncSocket(base_, fd, &clientAddr));
    tinfo.tfoSucceded = sock->getTFOSucceded();
    for (const auto& cb : observerList_.getAll()) {
      cb->accept(sock.get());
    }
    plaintextConnectionReady(std::move(sock), clientAddr, tinfo);
  }
}

void Acceptor::startHandshakeManager(
    AsyncSSLSocket::UniquePtr sslSock,
    Acceptor*,
    const SocketAddress& clientAddr,
    std::chrono::steady_clock::time_point acceptTime,
    TransportInfo& tinfo) noexcept {
  auto manager = securityProtocolCtxManager_.getHandshakeManager(
      this, clientAddr, acceptTime, tinfo);
  manager->start(std::move(sslSock));
}

void Acceptor::connectionReady(
    AsyncTransport::UniquePtr sock,
    const SocketAddress& clientAddr,
    const string& nextProtocolName,
    SecureTransportType secureTransportType,
    TransportInfo& tinfo) {
  if (state_ >= State::kDraining) {
    return;
  }

  // Limit the number of reads from tclshe socket per poll loop iteration,
  // both to keep memory usage under control and to prevent one fast-
  // writing client from starving other connections.
  auto asyncSocket = sock->getUnderlyingTransport<AsyncSocket>();
  asyncSocket->setMaxReadsPerEvent(accConfig_.socketMaxReadsPerEvent);
  tinfo.initWithSocket(asyncSocket);
  tinfo.appProtocol = std::make_shared<std::string>(nextProtocolName);

  for (const auto& cb : observerList_.getAll()) {
    cb->ready(sock.get());
  }

  folly::AsyncTransport::UniquePtr transformed =
      transformTransport(std::move(sock));

  onNewConnection(
      std::move(transformed),
      &clientAddr,
      nextProtocolName,
      secureTransportType,
      tinfo);
}

void Acceptor::plaintextConnectionReady(
    AsyncSocket::UniquePtr sock,
    const SocketAddress& clientAddr,
    TransportInfo& tinfo) {
  connectionReady(
      std::move(sock), clientAddr, {}, SecureTransportType::NONE, tinfo);
}

void Acceptor::sslConnectionReady(
    AsyncTransport::UniquePtr sock,
    const SocketAddress& clientAddr,
    const string& nextProtocol,
    SecureTransportType secureTransportType,
    TransportInfo& tinfo) {
  CHECK(numPendingSSLConns_ > 0);
  --numPendingSSLConns_;
  connectionReady(
      std::move(sock), clientAddr, nextProtocol, secureTransportType, tinfo);
  if (state_ == State::kDraining) {
    checkDrained();
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant