Merge commit '64f2f2734ad853784bdd260bcf31e065c47c0741' into fix-configure-pthread...
[folly.git] / folly / io / async / AsyncServerSocket.h
index 449b5a4a483484fdd83b5c3bd472df8db4b84395..a932f4e4d1ad43f9a98a6685cf814ac42c969721 100644 (file)
 #include <stddef.h>
 #include <sys/socket.h>
 
+
+// Due to the way kernel headers are included, this may or may not be defined.
+// Number pulled from 3.10 kernel headers.
+#ifndef SO_REUSEPORT
+#define SO_REUSEPORT 15
+#endif
+
 namespace folly {
 
 /**
@@ -248,6 +255,17 @@ class AsyncServerSocket : public DelayedDestruction {
    */
   virtual void bind(const SocketAddress& address);
 
+  /**
+   * Bind to the specified port for the specified addresses.
+   *
+   * This must be called from the primary EventBase thread.
+   *
+   * Throws TTransportException on error.
+   */
+  virtual void bind(
+      const std::vector<IPAddress>& ipAddresses,
+      uint16_t port);
+
   /**
    * Bind to the specified port.
    *
@@ -510,6 +528,36 @@ class AsyncServerSocket : public DelayedDestruction {
     return keepAliveEnabled_;
   }
 
+  /**
+   * Set whether or not SO_REUSEPORT should be enabled on the server socket,
+   * allowing multiple binds to the same port
+   */
+  void setReusePortEnabled(bool enabled) {
+    reusePortEnabled_ = enabled;
+
+    for (auto& handler : sockets_) {
+      if (handler.socket_ < 0) {
+        continue;
+      }
+
+      int val = (enabled) ? 1 : 0;
+      if (setsockopt(handler.socket_, SOL_SOCKET,
+                     SO_REUSEPORT, &val, sizeof(val)) != 0) {
+        LOG(ERROR) <<
+          "failed to set SO_REUSEPORT on async server socket " << errno;
+        folly::throwSystemError(errno,
+                                "failed to bind to async server socket");
+      }
+    }
+  }
+
+  /**
+   * Get whether or not SO_REUSEPORT is enabled on the server socket.
+   */
+  bool getReusePortEnabled_() const {
+    return reusePortEnabled_;
+  }
+
   /**
    * Set whether or not the socket should close during exec() (FD_CLOEXEC). By
    * default, this is enabled
@@ -602,6 +650,7 @@ class AsyncServerSocket : public DelayedDestruction {
 
   int createSocket(int family);
   void setupSocket(int fd);
+  void bindSocket(int fd, const SocketAddress& address, bool isExistingSocket);
   void dispatchSocket(int socket, SocketAddress&& address);
   void dispatchError(const char *msg, int errnoValue);
   void enterBackoff();
@@ -675,6 +724,7 @@ class AsyncServerSocket : public DelayedDestruction {
   BackoffTimeout *backoffTimeout_;
   std::vector<CallbackInfo> callbacks_;
   bool keepAliveEnabled_;
+  bool reusePortEnabled_{false};
   bool closeOnExec_;
   ShutdownSocketSet* shutdownSocketSet_;
 };