From 0f8ef0c29a9617113f1d365d5af01149a5417f92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Thu, 3 Feb 2022 10:35:04 +0100
Subject: [PATCH] Find automatically a free port when 0 is given as an argument

This follows the C standard. This is particularly useful for unit
testing socket interface.
---
 src/utils/Socket.cpp | 22 ++++++++++++++++++++--
 src/utils/Socket.hpp |  2 ++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/utils/Socket.cpp b/src/utils/Socket.cpp
index fec9e2ee8..503dac183 100644
--- a/src/utils/Socket.cpp
+++ b/src/utils/Socket.cpp
@@ -55,6 +55,12 @@ class Socket::Internals
     return m_is_server_socket;
   }
 
+  int
+  portNumber() const
+  {
+    return ::ntohs(m_address.sin_port);
+  }
+
   int
   fileDescriptor() const
   {
@@ -83,6 +89,12 @@ operator<<(std::ostream& os, const Socket& socket)
   return os << *socket.m_internals;
 }
 
+int
+Socket::portNumber() const
+{
+  return m_internals->portNumber();
+}
+
 Socket
 createServerSocket(int port_number)
 {
@@ -101,8 +113,14 @@ createServerSocket(int port_number)
   int on = 1;
   ::setsockopt(socket_internals.m_socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
 
-  if (::bind(socket_internals.m_socket_fd, reinterpret_cast<sockaddr*>(&socket_internals.m_address),
-             sizeof(socket_internals.m_address)) < 0) {
+  socklen_t length = sizeof(socket_internals.m_address);
+
+  if (::bind(socket_internals.m_socket_fd, reinterpret_cast<sockaddr*>(&socket_internals.m_address), length) < 0) {
+    throw NormalError(strerror(errno));
+  }
+
+  if (::getsockname(socket_internals.m_socket_fd, reinterpret_cast<sockaddr*>(&socket_internals.m_address), &length) ==
+      -1) {
     throw NormalError(strerror(errno));
   }
 
diff --git a/src/utils/Socket.hpp b/src/utils/Socket.hpp
index b8ee7201d..6b47fa4f0 100644
--- a/src/utils/Socket.hpp
+++ b/src/utils/Socket.hpp
@@ -19,6 +19,8 @@ class Socket
   void _read(char* data, const size_t lenght) const;
 
  public:
+  int portNumber() const;
+
   friend std::ostream& operator<<(std::ostream& os, const Socket& s);
 
   friend Socket createServerSocket(int port_number);
-- 
GitLab