Index: lldb/trunk/gtest/gtest.xcodeproj/project.pbxproj =================================================================== --- lldb/trunk/gtest/gtest.xcodeproj/project.pbxproj +++ lldb/trunk/gtest/gtest.xcodeproj/project.pbxproj @@ -12,6 +12,10 @@ 236ED33619D490B0008CA7D7 /* Makefile.rules */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.rules; sourceTree = ""; }; 33064C981A5C7A1A0033D415 /* UriParserTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParserTest.cpp; path = Utility/UriParserTest.cpp; sourceTree = ""; }; 33064C9D1A5C7AC90033D415 /* do-gtest.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = "do-gtest.py"; sourceTree = ""; }; + 330E475C1A609CF600FD2884 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Host/Makefile; sourceTree = ""; }; + 330E475D1A609CF600FD2884 /* SocketTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SocketTest.cpp; path = Host/SocketTest.cpp; sourceTree = ""; }; + 330E475E1A60B31F00FD2884 /* SocketTestMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SocketTestMock.cpp; path = Host/SocketTestMock.cpp; sourceTree = ""; }; + 330E47621A62451800FD2884 /* SocketAddressTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SocketAddressTest.cpp; path = Host/SocketAddressTest.cpp; sourceTree = ""; }; 338C47F41A1E67B900B46077 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Utility/Makefile; sourceTree = ""; }; 338C47F51A1E67B900B46077 /* StringExtractorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractorTest.cpp; path = Utility/StringExtractorTest.cpp; sourceTree = ""; }; /* End PBXFileReference section */ @@ -20,6 +24,7 @@ 236ED32F19D4901D008CA7D7 /* unittest */ = { isa = PBXGroup; children = ( + 330E475B1A609CDF00FD2884 /* Host */, 338C47F31A1E677900B46077 /* Utility */, 236ED33019D4903E008CA7D7 /* Plugins */, ); @@ -68,6 +73,17 @@ ); sourceTree = ""; }; + 330E475B1A609CDF00FD2884 /* Host */ = { + isa = PBXGroup; + children = ( + 330E475E1A60B31F00FD2884 /* SocketTestMock.cpp */, + 330E475C1A609CF600FD2884 /* Makefile */, + 330E475D1A609CF600FD2884 /* SocketTest.cpp */, + 330E47621A62451800FD2884 /* SocketAddressTest.cpp */, + ); + name = Host; + sourceTree = ""; + }; 338C47F31A1E677900B46077 /* Utility */ = { isa = PBXGroup; children = ( Index: lldb/trunk/gtest/unittest/Host/Makefile =================================================================== --- lldb/trunk/gtest/unittest/Host/Makefile +++ lldb/trunk/gtest/unittest/Host/Makefile @@ -0,0 +1,32 @@ +THIS_FILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/ + +LEVEL := $(realpath $(THIS_FILE_DIR)../../make) + +CFLAGS_EXTRAS := -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS +ENABLE_THREADS := YES +# the fact that we need all of these source files to compile Socket.cpp +# is a good indication that we need some refactoring +CXX_SOURCES := $(wildcard *.cpp) \ + $(realpath $(LEVEL)/../../source/Core/Error.cpp) \ + $(realpath $(LEVEL)/../../source/Core/RegularExpression.cpp) \ + $(realpath $(LEVEL)/../../source/Core/Stream.cpp) \ + $(realpath $(LEVEL)/../../source/Core/StreamString.cpp) \ + $(realpath $(LEVEL)/../../source/Host/common/Socket.cpp) \ + $(realpath $(LEVEL)/../../source/Host/common/SocketAddress.cpp) \ + $(realpath $(LEVEL)/../../source/Host/common/StringConvert.cpp) \ + $(realpath $(LEVEL)/../../source/Host/common/TimeValue.cpp) + +OS := $(shell uname -s) +ifeq ($(OS),Windows) +CXX_SOURCES := $(CXX_SOURCES) \ + $(LEVEL)/../../source/Host/windows/Condition.cpp \ + $(LEVEL)/../../source/Host/windows/Mutex.cpp +else +CXX_SOURCES := $(CXX_SOURCES) \ + $(LEVEL)/../../source/Host/common/Condition.cpp \ + $(LEVEL)/../../source/Host/common/Mutex.cpp +endif + +MAKE_DSYM := NO + +include $(LEVEL)/Makefile.rules Index: lldb/trunk/gtest/unittest/Host/SocketAddressTest.cpp =================================================================== --- lldb/trunk/gtest/unittest/Host/SocketAddressTest.cpp +++ lldb/trunk/gtest/unittest/Host/SocketAddressTest.cpp @@ -0,0 +1,77 @@ +//===-- SocketAddressTest.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "gtest/gtest.h" + +#include "lldb/Host/SocketAddress.h" + +namespace +{ + class SocketAddressTest: public ::testing::Test + { + }; +} + +using namespace lldb_private; + +TEST_F (SocketAddressTest, Set) +{ + SocketAddress sa; + ASSERT_TRUE (sa.SetToLocalhost (AF_INET, 1138)); + ASSERT_STREQ ("127.0.0.1", sa.GetIPAddress ().c_str ()); + ASSERT_EQ (1138, sa.GetPort ()); + + ASSERT_TRUE (sa.SetToAnyAddress (AF_INET, 0)); + ASSERT_STREQ ("0.0.0.0", sa.GetIPAddress ().c_str ()); + ASSERT_EQ (0, sa.GetPort ()); + + ASSERT_TRUE (sa.SetToLocalhost (AF_INET6, 1139)); +#ifdef _WIN32 + ASSERT_STREQ ("0:0:0:0:0:0:0:1", sa.GetIPAddress ().c_str ()); +#else + ASSERT_STREQ ("::1", sa.GetIPAddress ().c_str ()); +#endif + ASSERT_EQ (1139, sa.GetPort ()); +} + +#ifdef _WIN32 + +// we need to test our inet_ntop implementation for Windows XP +const char* inet_ntop (int af, const void * src, + char * dst, socklen_t size); + +TEST_F (SocketAddressTest, inet_ntop) +{ + const uint8_t address4[4] = {255, 0, 1, 100}; + const uint8_t address6[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 255, 0}; + + char buffer[INET6_ADDRSTRLEN]; + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ ("1:203:405:607:809:a0b:c0d:ff00", inet_ntop (AF_INET6, address6, buffer, sizeof (buffer))); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ ("1:203:405:607:809:a0b:c0d:ff00", inet_ntop (AF_INET6, address6, buffer, 31)); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ (nullptr, inet_ntop (AF_INET6, address6, buffer, 0)); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ (nullptr, inet_ntop (AF_INET6, address6, buffer, 30)); + + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ ("255.0.1.100", inet_ntop (AF_INET, address4, buffer, sizeof (buffer))); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ ("255.0.1.100", inet_ntop (AF_INET, address4, buffer, 12)); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ (nullptr, inet_ntop (AF_INET, address4, buffer, 0)); + memset (buffer, 'x', sizeof (buffer)); + EXPECT_STREQ (nullptr, inet_ntop (AF_INET, address4, buffer, 11)); +} + +#endif + + Index: lldb/trunk/gtest/unittest/Host/SocketTest.cpp =================================================================== --- lldb/trunk/gtest/unittest/Host/SocketTest.cpp +++ lldb/trunk/gtest/unittest/Host/SocketTest.cpp @@ -0,0 +1,132 @@ +//===-- SocketTest.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +#include "gtest/gtest.h" + +#include "lldb/Host/Socket.h" + +class SocketTest: public ::testing::Test +{ +}; + +using namespace lldb_private; + +void AcceptThread (Socket* listen_socket, + const char* listen_remote_address, + bool child_processes_inherit, + Socket** accept_socket, + Error* error) +{ + *error = listen_socket->BlockingAccept (listen_remote_address, child_processes_inherit, *accept_socket); +} + +void CreateConnectedSockets (std::unique_ptr* a_up, std::unique_ptr* b_up) +{ + Predicate port_predicate; + // Used when binding to port zero to wait for the thread + // that creates the socket, binds and listens to resolve + // the port number. + + port_predicate.SetValue (0, eBroadcastNever); + + bool child_processes_inherit = false; + Socket *socket = nullptr; + const char* listen_remote_address = "localhost:0"; + Error error = Socket::TcpListen (listen_remote_address, child_processes_inherit, socket, &port_predicate); + std::unique_ptr listen_socket_up (socket); + socket = nullptr; + EXPECT_FALSE (error.Fail ()); + EXPECT_NE (nullptr, listen_socket_up.get ()); + EXPECT_TRUE (listen_socket_up->IsValid ()); + + Error accept_error; + Socket* accept_socket; + std::thread accept_thread (AcceptThread, + listen_socket_up.get (), + listen_remote_address, + child_processes_inherit, + &accept_socket, + &accept_error); + + char connect_remote_address[64]; + snprintf (connect_remote_address, sizeof (connect_remote_address), "localhost:%u", port_predicate.GetValue ()); + error = Socket::TcpConnect (connect_remote_address, child_processes_inherit, socket); + a_up->reset (socket); + socket = nullptr; + EXPECT_TRUE (error.Success ()); + EXPECT_NE (nullptr, a_up->get ()); + EXPECT_TRUE ((*a_up)->IsValid ()); + + accept_thread.join (); + b_up->reset (accept_socket); + EXPECT_TRUE (accept_error.Success ()); + EXPECT_NE (nullptr, b_up->get ()); + EXPECT_TRUE ((*b_up)->IsValid ()); + + listen_socket_up.reset (); +} + +TEST_F (SocketTest, DecodeHostAndPort) +{ + std::string host_str; + std::string port_str; + int32_t port; + Error error; + EXPECT_TRUE (Socket::DecodeHostAndPort ("localhost:1138", host_str, port_str, port, &error)); + EXPECT_STREQ ("localhost", host_str.c_str ()); + EXPECT_STREQ ("1138", port_str.c_str ()); + EXPECT_EQ (1138, port); + EXPECT_TRUE (error.Success ()); + + EXPECT_FALSE (Socket::DecodeHostAndPort ("google.com:65536", host_str, port_str, port, &error)); + EXPECT_TRUE (error.Fail ()); + EXPECT_STREQ ("invalid host:port specification: 'google.com:65536'", error.AsCString ()); + + EXPECT_FALSE (Socket::DecodeHostAndPort ("google.com:-1138", host_str, port_str, port, &error)); + EXPECT_TRUE (error.Fail ()); + EXPECT_STREQ ("invalid host:port specification: 'google.com:-1138'", error.AsCString ()); + + EXPECT_TRUE (Socket::DecodeHostAndPort ("12345", host_str, port_str, port, &error)); + EXPECT_STREQ ("", host_str.c_str ()); + EXPECT_STREQ ("12345", port_str.c_str ()); + EXPECT_EQ (12345, port); + EXPECT_TRUE (error.Success ()); + + EXPECT_TRUE (Socket::DecodeHostAndPort ("*:0", host_str, port_str, port, &error)); + EXPECT_STREQ ("*", host_str.c_str ()); + EXPECT_STREQ ("0", port_str.c_str ()); + EXPECT_EQ (0, port); + EXPECT_TRUE (error.Success ()); + +} + +TEST_F (SocketTest, Listen0ConnectAccept) +{ + std::unique_ptr socket_a_up; + std::unique_ptr socket_b_up; + CreateConnectedSockets (&socket_a_up, &socket_b_up); +} + +TEST_F (SocketTest, GetAddress) +{ + std::unique_ptr socket_a_up; + std::unique_ptr socket_b_up; + CreateConnectedSockets (&socket_a_up, &socket_b_up); + + EXPECT_EQ (socket_a_up->GetLocalPortNumber (), socket_b_up->GetRemotePortNumber ()); + EXPECT_EQ (socket_b_up->GetLocalPortNumber (), socket_a_up->GetRemotePortNumber ()); + EXPECT_NE (socket_a_up->GetLocalPortNumber (), socket_b_up->GetLocalPortNumber ()); + EXPECT_STREQ ("127.0.0.1", socket_a_up->GetRemoteIPAddress ().c_str ()); + EXPECT_STREQ ("127.0.0.1", socket_b_up->GetRemoteIPAddress ().c_str ()); +} + + + Index: lldb/trunk/gtest/unittest/Host/SocketTestMock.cpp =================================================================== --- lldb/trunk/gtest/unittest/Host/SocketTestMock.cpp +++ lldb/trunk/gtest/unittest/Host/SocketTestMock.cpp @@ -0,0 +1,64 @@ +//===-- SocketTestMock.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This file provides a few necessary functions to link SocketTest.cpp +// Bringing in the real implementations results in a cascade of dependencies +// that pull in all of lldb. + +#include "lldb/Core/Log.h" + +#ifdef _WIN32 +#include +#endif + +using namespace lldb_private; + +void +lldb_private::Log::Error (char const*, ...) +{ +} + +void +lldb_private::Log::Printf (char const*, ...) +{ +} + +Log* +lldb_private::GetLogIfAnyCategoriesSet (unsigned int) +{ + return nullptr; +} + +#include "lldb/Host/FileSystem.h" + +#ifdef _WIN32 + +Error +FileSystem::Unlink(const char *path) +{ + Error error; + BOOL result = ::DeleteFile(path); + if (!result) + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; +} + +#else + +Error +FileSystem::Unlink (const char *path) +{ + Error error; + if (::unlink (path) == -1) + error.SetErrorToErrno (); + return error; +} + +#endif + Index: lldb/trunk/include/lldb/Host/Socket.h =================================================================== --- lldb/trunk/include/lldb/Host/Socket.h +++ lldb/trunk/include/lldb/Host/Socket.h @@ -70,22 +70,35 @@ int GetOption (int level, int option_name, int &option_value); int SetOption (int level, int option_name, int option_value); - static uint16_t GetPortNumber(const NativeSocket& socket); - uint16_t GetPortNumber () const; + // returns port number or 0 if error + static uint16_t GetLocalPortNumber (const NativeSocket& socket); + + // returns port number or 0 if error + uint16_t GetLocalPortNumber () const; + + // returns ip address string or empty string if error + std::string GetLocalIPAddress () const; + + // must be connected + // returns port number or 0 if error + uint16_t GetRemotePortNumber () const; + + // must be connected + // returns ip address string or empty string if error + std::string GetRemoteIPAddress () const; NativeSocket GetNativeSocket () const { return m_socket; } - SocketProtocol GetSocketProtocol() const { return m_protocol; } + SocketProtocol GetSocketProtocol () const { return m_protocol; } virtual Error Read (void *buf, size_t &num_bytes); virtual Error Write (const void *buf, size_t &num_bytes); - virtual Error PreDisconnect(); - virtual Error Close(); + virtual Error PreDisconnect (); + virtual Error Close (); - virtual bool IsValid() const { return m_socket != kInvalidSocketValue; } - virtual WaitableHandle GetWaitableHandle(); + virtual bool IsValid () const { return m_socket != kInvalidSocketValue; } + virtual WaitableHandle GetWaitableHandle (); -protected: static bool DecodeHostAndPort (llvm::StringRef host_and_port, std::string &host_str, @@ -93,7 +106,7 @@ int32_t& port, Error *error_ptr); - +protected: SocketProtocol m_protocol; NativeSocket m_socket; SocketAddress m_udp_send_sockaddr; // Send address used for UDP connections. Index: lldb/trunk/include/lldb/Host/SocketAddress.h =================================================================== --- lldb/trunk/include/lldb/Host/SocketAddress.h +++ lldb/trunk/include/lldb/Host/SocketAddress.h @@ -31,6 +31,7 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include namespace lldb_private { @@ -100,6 +101,12 @@ SetFamily (sa_family_t family); //------------------------------------------------------------------ + // Get the address + //------------------------------------------------------------------ + std::string + GetIPAddress () const; + + //------------------------------------------------------------------ // Get the port if the socket address for the family has a port //------------------------------------------------------------------ uint16_t Index: lldb/trunk/source/Host/common/Socket.cpp =================================================================== --- lldb/trunk/source/Host/common/Socket.cpp +++ lldb/trunk/source/Host/common/Socket.cpp @@ -222,7 +222,7 @@ // as port zero is a special code for "find an open port // for me". if (port == 0) - port = listen_socket->GetPortNumber(); + port = listen_socket->GetLocalPortNumber(); // Set the port predicate since when doing a listen://: // it often needs to accept the incoming connection which is a blocking @@ -230,7 +230,7 @@ // us to wait for the port predicate to be set to a non-zero value from // another thread in an efficient manor. if (predicate) - predicate->SetValue(port, eBroadcastAlways); + predicate->SetValue (port, eBroadcastAlways); socket = listen_socket.release(); } @@ -533,13 +533,18 @@ if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) && regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str)) { - port = StringConvert::ToSInt32 (port_str.c_str(), INT32_MIN); - if (port != INT32_MIN) + bool ok = false; + port = StringConvert::ToUInt32 (port_str.c_str(), UINT32_MAX, 10, &ok); + if (ok && port < UINT16_MAX) { if (error_ptr) error_ptr->Clear(); return true; } + // port is too large + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data()); + return false; } } @@ -547,10 +552,13 @@ // a port with an empty host. host_str.clear(); port_str.clear(); - port = StringConvert::ToSInt32(host_and_port.data(), INT32_MIN); - if (port != INT32_MIN) + bool ok = false; + port = StringConvert::ToUInt32 (host_and_port.data(), UINT32_MAX, 10, &ok); + if (ok && port < UINT16_MAX) { port_str = host_and_port; + if (error_ptr) + error_ptr->Clear(); return true; } @@ -688,7 +696,7 @@ return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value)); } -uint16_t Socket::GetPortNumber(const NativeSocket& socket) +uint16_t Socket::GetLocalPortNumber(const NativeSocket& socket) { // We bound to port zero, so we need to figure out which port we actually bound to if (socket >= 0) @@ -702,7 +710,47 @@ } // Return the port number that is being used by the socket. -uint16_t Socket::GetPortNumber() const +uint16_t Socket::GetLocalPortNumber() const { - return GetPortNumber(m_socket); + return GetLocalPortNumber (m_socket); } + +std::string Socket::GetLocalIPAddress () const +{ + // We bound to port zero, so we need to figure out which port we actually bound to + if (m_socket >= 0) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress (); + } + return ""; +} + +uint16_t Socket::GetRemotePortNumber () const +{ + if (m_socket >= 0) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetPort (); + } + return 0; +} + +std::string Socket::GetRemoteIPAddress () const +{ + // We bound to port zero, so we need to figure out which port we actually bound to + if (m_socket >= 0) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress (); + } + return ""; +} + + Index: lldb/trunk/source/Host/common/SocketAddress.cpp =================================================================== --- lldb/trunk/source/Host/common/SocketAddress.cpp +++ lldb/trunk/source/Host/common/SocketAddress.cpp @@ -21,6 +21,56 @@ // Other libraries and framework includes // Project includes +// WindowsXP needs an inet_ntop implementation +#ifdef _WIN32 + +#ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs +#define INET6_ADDRSTRLEN 46 +#endif + +// TODO: implement shortened form "::" for runs of zeros +const char* inet_ntop(int af, const void * src, + char * dst, socklen_t size) +{ + if (size==0) + { + return nullptr; + } + + switch (af) + { + case AF_INET: + { + const char* formatted = inet_ntoa(*static_cast(src)); + if (formatted && strlen(formatted) < size) + { + strncpy(dst, formatted, size); + return dst; + } + return nullptr; + case AF_INET6: + { + char tmp[INET6_ADDRSTRLEN] = {0}; + const uint16_t* src16 = static_cast(src); + int full_size = _snprintf(tmp, sizeof(tmp), + "%x:%x:%x:%x:%x:%x:%x:%x", + ntohs(src16[0]), ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), + ntohs(src16[4]), ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7]) + ); + if (full_size < size) + { + strncpy(dst,tmp,size); + return dst; + } + return nullptr; + } + } + return nullptr; + } + +#endif + + using namespace lldb_private; //---------------------------------------------------------------------- @@ -124,6 +174,26 @@ #endif } +std::string +SocketAddress::GetIPAddress () const +{ + char str[INET6_ADDRSTRLEN] = {0}; + switch (GetFamily()) + { + case AF_INET: + if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, sizeof(str))) + { + return str; + } + case AF_INET6: + if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, sizeof(str))) + { + return str; + } + } + return ""; +} + uint16_t SocketAddress::GetPort () const { Index: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -274,7 +274,7 @@ if (conn_ap->IsConnected()) { const Socket& socket = static_cast(*conn_ap->GetReadObject()); - const uint16_t reply_port = socket.GetPortNumber(); + const uint16_t reply_port = socket.GetLocalPortNumber(); if (reply_port != 0) {