diff --git a/lib/netplay/connection_address.cpp b/lib/netplay/connection_address.cpp deleted file mode 100644 index e4c277b8c50..00000000000 --- a/lib/netplay/connection_address.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of Warzone 2100. - Copyright (C) 2024 Warzone 2100 Project - - Warzone 2100 is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - Warzone 2100 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Warzone 2100; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "lib/netplay/connection_address.h" -#include "lib/netplay/tcp/netsocket.h" // for `resolveHost` - -#include "lib/framework/frame.h" // for `ASSERT` - -struct ConnectionAddress::Impl final -{ - explicit Impl(SocketAddress* addr) - : mAddr_(addr) - {} - - ~Impl() - { - ASSERT(mAddr_ != nullptr, "Invalid addrinfo stored in the connection address"); - freeaddrinfo(mAddr_); - } - - SocketAddress* mAddr_; -}; - -ConnectionAddress::ConnectionAddress() = default; -ConnectionAddress::ConnectionAddress(ConnectionAddress&&) = default; -ConnectionAddress::~ConnectionAddress() = default; - -const SocketAddress* ConnectionAddress::asRawSocketAddress() const -{ - return mPimpl_->mAddr_; -} - - -net::result ConnectionAddress::parse(const char* hostname, uint16_t port) -{ - ConnectionAddress res; - const auto addr = tcp::resolveHost(hostname, port); - if (!addr.has_value()) - { - return tl::make_unexpected(addr.error()); - } - res.mPimpl_ = std::make_unique(addr.value()); - return net::result{std::move(res)}; -} - -net::result ConnectionAddress::parse(const std::string& hostname, uint16_t port) -{ - return parse(hostname.c_str(), port); -} diff --git a/lib/netplay/connection_address.h b/lib/netplay/connection_address.h index 604d9dc12da..876a46ea745 100644 --- a/lib/netplay/connection_address.h +++ b/lib/netplay/connection_address.h @@ -23,13 +23,7 @@ #include "lib/netplay/net_result.h" -#if defined WZ_OS_UNIX -# include -#elif defined WZ_OS_WIN -# include -#endif -typedef struct addrinfo SocketAddress; /// /// Opaque class representing abstract connection address to use with various @@ -50,23 +44,7 @@ typedef struct addrinfo SocketAddress; /// New conversion routines should be introduced for other network backends, /// if deemed necessary. /// -class ConnectionAddress +struct IConnectionAddress { -public: - - ConnectionAddress(); - ConnectionAddress(ConnectionAddress&&); - ConnectionAddress(const ConnectionAddress&) = delete; - ~ConnectionAddress(); - - static net::result parse(const char* hostname, uint16_t port); - static net::result parse(const std::string& hostname, uint16_t port); - - // NOTE: The lifetime of the returned `addrinfo` struct is bounded by the parent object's lifetime! - const SocketAddress* asRawSocketAddress() const; - -private: - - struct Impl; - std::unique_ptr mPimpl_; + virtual ~IConnectionAddress() = default; }; diff --git a/lib/netplay/netplay.cpp b/lib/netplay/netplay.cpp index 54144392caa..1f725e07014 100644 --- a/lib/netplay/netplay.cpp +++ b/lib/netplay/netplay.cpp @@ -3467,7 +3467,7 @@ bool LobbyServerConnectionHandler::connect() } // try each address from resolveHost until we successfully connect. - auto sockResult = connProvider.openClientConnectionAny(hosts, 1500); + auto sockResult = connProvider.openClientConnectionAny(*hosts, 1500); rs_socket = sockResult.value_or(nullptr); @@ -4664,7 +4664,7 @@ bool NETenumerateGames(const std::function& handl return false; } const auto& hosts = hostsResult.value(); - auto sockResult = connProvider.openClientConnectionAny(hosts, 15000); + auto sockResult = connProvider.openClientConnectionAny(*hosts, 15000); if (!sockResult.has_value()) { const auto sockErrMsg = sockResult.error().message(); diff --git a/lib/netplay/tcp/tcp_connection_address.cpp b/lib/netplay/tcp/tcp_connection_address.cpp new file mode 100644 index 00000000000..66f7d1981e7 --- /dev/null +++ b/lib/netplay/tcp/tcp_connection_address.cpp @@ -0,0 +1,30 @@ +/* + This file is part of Warzone 2100. + Copyright (C) 2024 Warzone 2100 Project + Warzone 2100 is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + Warzone 2100 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Warzone 2100; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "lib/netplay/tcp/tcp_connection_address.h" + +#include "lib/netplay/tcp/netsocket.h" // for `freeaddrinfo` +#include "lib/framework/frame.h" // for `ASSERT` + +TCPConnectionAddress::TCPConnectionAddress(SocketAddress* addr) + : addr_(addr) +{} + +TCPConnectionAddress::~TCPConnectionAddress() +{ + ASSERT(addr_ != nullptr, "Invalid addrinfo stored in the connection address"); + freeaddrinfo(addr_); +} diff --git a/lib/netplay/tcp/tcp_connection_address.h b/lib/netplay/tcp/tcp_connection_address.h new file mode 100644 index 00000000000..fdc7b0b6d76 --- /dev/null +++ b/lib/netplay/tcp/tcp_connection_address.h @@ -0,0 +1,43 @@ +/* + This file is part of Warzone 2100. + Copyright (C) 2024 Warzone 2100 Project + Warzone 2100 is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + Warzone 2100 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Warzone 2100; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include "lib/netplay/connection_address.h" + +#if defined WZ_OS_UNIX +# include +#elif defined WZ_OS_WIN +# include +#endif + +typedef struct addrinfo SocketAddress; + +class TCPConnectionAddress : public IConnectionAddress +{ +public: + + /// Assumes ownership of `addr` + explicit TCPConnectionAddress(SocketAddress* addr); + virtual ~TCPConnectionAddress() override; + + // NOTE: The lifetime of the returned `addrinfo` struct is bounded by the parent object's lifetime! + const SocketAddress* asRawSocketAddress() const { return addr_; } + +private: + + SocketAddress* addr_; +}; diff --git a/lib/netplay/tcp/tcp_connection_provider.cpp b/lib/netplay/tcp/tcp_connection_provider.cpp index 8a3182a02e7..d801fc05a14 100644 --- a/lib/netplay/tcp/tcp_connection_provider.cpp +++ b/lib/netplay/tcp/tcp_connection_provider.cpp @@ -20,6 +20,7 @@ #include "tcp_connection_provider.h" #include "lib/netplay/tcp/netsocket.h" +#include "lib/netplay/tcp/tcp_connection_address.h" #include "lib/netplay/tcp/tcp_connection_poll_group.h" #include "lib/netplay/tcp/tcp_client_connection.h" #include "lib/netplay/tcp/tcp_listen_socket.h" @@ -40,9 +41,14 @@ void TCPConnectionProvider::shutdown() SOCKETshutdown(); } -net::result TCPConnectionProvider::resolveHost(const char* host, uint16_t port) +net::result> TCPConnectionProvider::resolveHost(const char* host, uint16_t port) { - return ConnectionAddress::parse(host, port); + auto resolved = tcp::resolveHost(host, port); + if (!resolved.has_value()) + { + return tl::make_unexpected(resolved.error()); + } + return std::make_unique(resolved.value()); } net::result TCPConnectionProvider::openListenSocket(uint16_t port) @@ -55,9 +61,15 @@ net::result TCPConnectionProvider::openListenSocket(uint16_t por return new TCPListenSocket(res.value()); } -net::result TCPConnectionProvider::openClientConnectionAny(const ConnectionAddress& addr, unsigned timeout) +net::result TCPConnectionProvider::openClientConnectionAny(const IConnectionAddress& addr, unsigned timeout) { - const auto* rawAddr = addr.asRawSocketAddress(); + const auto* tcpAddr = dynamic_cast(&addr); + ASSERT(tcpAddr != nullptr, "Expected TCPConnectionAddress instance"); + if (!tcpAddr) + { + throw std::runtime_error("Expected TCPConnectionAddress instance"); + } + const auto* rawAddr = tcpAddr->asRawSocketAddress(); auto res = socketOpenAny(rawAddr, timeout); if (!res.has_value()) { diff --git a/lib/netplay/tcp/tcp_connection_provider.h b/lib/netplay/tcp/tcp_connection_provider.h index 9a1336558b3..c34add18b1e 100644 --- a/lib/netplay/tcp/tcp_connection_provider.h +++ b/lib/netplay/tcp/tcp_connection_provider.h @@ -35,11 +35,11 @@ class TCPConnectionProvider final : public WzConnectionProvider virtual void initialize() override; virtual void shutdown() override; - virtual net::result resolveHost(const char* host, uint16_t port) override; + virtual net::result> resolveHost(const char* host, uint16_t port) override; virtual net::result openListenSocket(uint16_t port) override; - virtual net::result openClientConnectionAny(const ConnectionAddress& addr, unsigned timeout) override; + virtual net::result openClientConnectionAny(const IConnectionAddress& addr, unsigned timeout) override; virtual bool openClientConnectionAsync(const std::string& host, uint32_t port, OpenConnectionToHostResultCallback callback) override; virtual IConnectionPollGroup* newConnectionPollGroup() override; diff --git a/lib/netplay/wz_connection_provider.h b/lib/netplay/wz_connection_provider.h index 1c9d51dbd8e..9a9d879ff66 100644 --- a/lib/netplay/wz_connection_provider.h +++ b/lib/netplay/wz_connection_provider.h @@ -20,6 +20,7 @@ #pragma once #include +#include #include "lib/netplay/connection_address.h" #include "lib/netplay/net_result.h" @@ -28,6 +29,7 @@ class IListenSocket; class IClientConnection; class IConnectionPollGroup; +struct IConnectionAddress; /// /// Abstraction layer to facilitate creating client/server connections and @@ -57,7 +59,7 @@ class WzConnectionProvider /// Resolve host + port combination and return an opaque `ConnectionAddress` handle /// representing the resolved network address. /// - virtual net::result resolveHost(const char* host, uint16_t port) = 0; + virtual net::result> resolveHost(const char* host, uint16_t port) = 0; /// /// Open a listening socket bound to a specified local port. /// @@ -68,7 +70,7 @@ class WzConnectionProvider /// /// Connection address to bind the client connection to. /// Timeout in milliseconds. - virtual net::result openClientConnectionAny(const ConnectionAddress& addr, unsigned timeout) = 0; + virtual net::result openClientConnectionAny(const IConnectionAddress& addr, unsigned timeout) = 0; /// /// Async variant of `openClientConnectionAny()`. /// diff --git a/po/POTFILES.in b/po/POTFILES.in index 1365f738c66..78dd4afab84 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -302,9 +302,8 @@ lib/ivis_opengl/png_util_spng.cpp lib/ivis_opengl/screen.cpp lib/ivis_opengl/tex.cpp lib/ivis_opengl/textdraw.cpp -lib/netplay/error_categories.cpp -lib/netplay/connection_address.cpp lib/netplay/connection_provider_registry.cpp +lib/netplay/error_categories.cpp lib/netplay/netjoin_stub.cpp lib/netplay/netlog.cpp lib/netplay/netpermissions.cpp