Keep the same listening socket in bssl server -loop.

When testing against a browser, multiple connections will be made in
parallel. Keeping the same listening socket lets the other connections
queue up at least rather than fail with ECONNREFUSED. Of course, this is
still far from a realistic server.

Change-Id: I984fb29da4bf8808eb40938b12782dc1730f2e19
Reviewed-on: https://boringssl-review.googlesource.com/17405
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/tool/server.cc b/tool/server.cc
index 53f9a9c..1d6d27c 100644
--- a/tool/server.cc
+++ b/tool/server.cc
@@ -233,10 +233,15 @@
     SSL_CTX_set_early_data_enabled(ctx.get(), 1);
   }
 
+  Listener listener;
+  if (!listener.Init(args_map["-accept"])) {
+    return false;
+  }
+
   bool result = true;
   do {
     int sock = -1;
-    if (!Accept(&sock, args_map["-accept"])) {
+    if (!listener.Accept(&sock)) {
       return false;
     }
 
diff --git a/tool/transport_common.cc b/tool/transport_common.cc
index cf1d5f8..912e680 100644
--- a/tool/transport_common.cc
+++ b/tool/transport_common.cc
@@ -149,48 +149,56 @@
   return ok;
 }
 
-bool Accept(int *out_sock, const std::string &port) {
-  struct sockaddr_in6 addr, cli_addr;
-  socklen_t cli_addr_len = sizeof(cli_addr);
+Listener::~Listener() {
+  if (server_sock_ >= 0) {
+    closesocket(server_sock_);
+  }
+}
+
+bool Listener::Init(const std::string &port) {
+  if (server_sock_ >= 0) {
+    return false;
+  }
+
+  struct sockaddr_in6 addr;
   OPENSSL_memset(&addr, 0, sizeof(addr));
 
   addr.sin6_family = AF_INET6;
   addr.sin6_addr = IN6ADDR_ANY_INIT;
   addr.sin6_port = htons(atoi(port.c_str()));
 
-  bool ok = false;
 #if defined(OPENSSL_WINDOWS)
   const BOOL enable = TRUE;
 #else
   const int enable = 1;
 #endif
-  int server_sock = -1;
 
-  server_sock =
-      socket(addr.sin6_family, SOCK_STREAM, 0);
-  if (server_sock < 0) {
+  server_sock_ = socket(addr.sin6_family, SOCK_STREAM, 0);
+  if (server_sock_ < 0) {
     perror("socket");
-    goto out;
+    return false;
   }
 
-  if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&enable,
+  if (setsockopt(server_sock_, SOL_SOCKET, SO_REUSEADDR, (const char *)&enable,
                  sizeof(enable)) < 0) {
     perror("setsockopt");
-    goto out;
+    return false;
   }
 
-  if (bind(server_sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
+  if (bind(server_sock_, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
     perror("connect");
-    goto out;
+    return false;
   }
-  listen(server_sock, 1);
-  *out_sock = accept(server_sock, (struct sockaddr*)&cli_addr, &cli_addr_len);
 
-  ok = true;
+  listen(server_sock_, SOMAXCONN);
+  return true;
+}
 
-out:
-  closesocket(server_sock);
-  return ok;
+bool Listener::Accept(int *out_sock) {
+  struct sockaddr_in6 addr;
+  socklen_t addr_len = sizeof(addr);
+  *out_sock = accept(server_sock_, (struct sockaddr *)&addr, &addr_len);
+  return *out_sock >= 0;
 }
 
 bool VersionFromString(uint16_t *out_version, const std::string &version) {
diff --git a/tool/transport_common.h b/tool/transport_common.h
index 7595f45..7c157ba 100644
--- a/tool/transport_common.h
+++ b/tool/transport_common.h
@@ -26,10 +26,24 @@
 // It returns true on success and false otherwise.
 bool Connect(int *out_sock, const std::string &hostname_and_port);
 
-// Accept sets |*out_sock| to be a socket connected to the port given
-// in |port|, which should be of the form "123".
-// It returns true on success and false otherwise.
-bool Accept(int *out_sock, const std::string &port);
+class Listener {
+ public:
+  Listener() {}
+  ~Listener();
+
+  // Init initializes the listener to listen on |port|, which should be of the
+  // form "123".
+  bool Init(const std::string &port);
+
+  // Accept sets |*out_sock| to be a socket connected to the listener.
+  bool Accept(int *out_sock);
+
+ private:
+  int server_sock_ = -1;
+
+  Listener(const Listener &) = delete;
+  Listener &operator=(const Listener &) = delete;
+};
 
 bool VersionFromString(uint16_t *out_version, const std::string &version);