void startAccepting()

in mcrouter/lib/network/AsyncMcServer.cpp [495:637]


  void startAccepting() {
    CHECK(accepting_);
    auto& opts = server_.opts_;

    if (!opts.existingSocketFds.empty()) {
      checkLogic(
          opts.ports.empty() && opts.sslPorts.empty(),
          "Can't use ports if using existing socket");
      checkLogic(
          !reusePort_,
          "Can't use multiple listening sockets option if using existing socket");

      // Don't enable tcpZeroCopy here as it will be inherited. It has to be
      // enabled when the socket is in a TCP_CLOSE state, afterwards its too
      // late.
      if (opts.worker.tcpZeroCopyThresholdBytes > 0) {
        for (auto fd : opts.existingSocketFds) {
          int val = 0;
          socklen_t optlen = sizeof(val);
          int ret = getsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &val, &optlen);
          checkLogic(!ret, "Failed to getsockopt existing FD");
          checkLogic(val, "SO_ZEROCOPY must be enabled on existing socket.");
        }
      }
      if (!opts.pemCertPath.empty() || !opts.pemKeyPath.empty() ||
          !opts.pemCaPath.empty()) {
        checkLogic(
            !opts.pemCertPath.empty() && !opts.pemKeyPath.empty() &&
                !opts.pemCaPath.empty(),
            "All of pemCertPath, pemKeyPath and pemCaPath are required "
            "if at least one of them set");

        sslSocket_.reset(new folly::AsyncServerSocket());
        std::vector<folly::NetworkSocket> sockets;
        for (auto fd : opts.existingSocketFds) {
          sockets.push_back(folly::NetworkSocket::fromFd(fd));
        }

        sslSocket_->useExistingSockets(sockets);
      } else {
        socket_.reset(new folly::AsyncServerSocket());
        std::vector<folly::NetworkSocket> sockets;
        for (auto fd : opts.existingSocketFds) {
          sockets.push_back(folly::NetworkSocket::fromFd(fd));
        }
        socket_->useExistingSockets(sockets);
      }
    } else if (!opts.unixDomainSockPath.empty()) {
      checkLogic(
          opts.ports.empty() && opts.sslPorts.empty() &&
              opts.existingSocketFds.empty(),
          "Can't listen on port and unix domain socket at the same time");
      checkLogic(
          !reusePort_,
          "Can't use multiple listening sockets option with unix domain sockets.");
      checkLogic(
          !opts.worker.tcpZeroCopyThresholdBytes,
          "Can't use tcp zero copy with unix domain sockets.");
      std::remove(opts.unixDomainSockPath.c_str());
      socket_.reset(new folly::AsyncServerSocket());
      folly::SocketAddress serverAddress;
      serverAddress.setFromPath(opts.unixDomainSockPath);
      socket_->bind(serverAddress);
    } else {
      checkLogic(
          !server_.opts_.ports.empty() || !server_.opts_.sslPorts.empty(),
          "At least one port (plain or SSL) must be speicified");
      if (!server_.opts_.ports.empty()) {
        socket_.reset(new folly::AsyncServerSocket());
        socket_->setReusePortEnabled(reusePort_);
        for (auto port : server_.opts_.ports) {
          if (server_.opts_.listenAddresses.empty()) {
            socket_->bind(port);
          } else {
            std::vector<folly::IPAddress> ipAddresses;
            for (auto& listenAddress : server_.opts_.listenAddresses) {
              auto maybeIp = folly::IPAddress::tryFromString(listenAddress);
              checkLogic(
                  maybeIp.hasValue(),
                  "Invalid listen address: {}",
                  listenAddress);
              auto ip = std::move(maybeIp).value();
              ipAddresses.push_back(std::move(ip));
            }
            socket_->bind(ipAddresses, port);
          }
        }
        if (opts.worker.tcpZeroCopyThresholdBytes > 0) {
          bool zeroCopyApplied = socket_->setZeroCopy(true);
          checkLogic(zeroCopyApplied, "Failed to set TCP zero copy on socket");
        }
        socket_->setTosReflect(server_.opts_.worker.tosReflection);
      }
      if (!server_.opts_.sslPorts.empty()) {
        checkLogic(
            !server_.opts_.pemCertPath.empty() &&
                !server_.opts_.pemKeyPath.empty() &&
                !server_.opts_.pemCaPath.empty(),
            "All of pemCertPath, pemKeyPath, pemCaPath required"
            " with sslPorts");

        sslSocket_.reset(new folly::AsyncServerSocket());
        sslSocket_->setReusePortEnabled(reusePort_);
        for (auto sslPort : server_.opts_.sslPorts) {
          sslSocket_->bind(sslPort);
        }
        if (opts.worker.tcpZeroCopyThresholdBytes > 0) {
          bool zeroCopyApplied = sslSocket_->setZeroCopy(true);
          checkLogic(
              zeroCopyApplied, "Failed to set TCP zero copy on ssl socket");
        }
        sslSocket_->setTosReflect(server_.opts_.worker.tosReflection);
      }
    }

    if (socket_) {
      socket_->listen(server_.opts_.tcpListenBacklog);
      socket_->startAccepting();
      socket_->attachEventBase(&eventBase());
    }
    if (sslSocket_) {
      if (server_.opts_.tfoEnabledForSsl) {
        sslSocket_->setTFOEnabled(true, server_.opts_.tfoQueueSize);
      } else {
        sslSocket_->setTFOEnabled(false, 0);
      }
      sslSocket_->listen(server_.opts_.tcpListenBacklog);
      sslSocket_->startAccepting();
      sslSocket_->attachEventBase(&eventBase());
    }

    for (auto& t : server_.threads_) {
      if (socket_ != nullptr) {
        socket_->addAcceptCallback(&t->acceptCallback_, &t->eventBase());
      }
      if (sslSocket_ != nullptr) {
        sslSocket_->addAcceptCallback(&t->sslAcceptCallback_, &t->eventBase());
      }
      if (socket_ != nullptr || sslSocket_ != nullptr || t.get() != this) {
        acceptorsKeepAlive_.emplace_back(getKeepAliveToken(&t->eventBase()));
      }
    }
  }