Skip to content

Commit

Permalink
netplay: introduce inheritance chain for connection address objects
Browse files Browse the repository at this point in the history
This way it looks much cleaner and naturally doesn't leak any
implementation details to clients. Also, now it's much
easier to provide native connection address implementations
for each backend implementation.

Signed-off-by: Pavel Solodovnikov <[email protected]>
  • Loading branch information
ManManson committed Nov 16, 2024
1 parent dbeec3f commit 7568a5c
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 101 deletions.
65 changes: 0 additions & 65 deletions lib/netplay/connection_address.cpp

This file was deleted.

26 changes: 2 additions & 24 deletions lib/netplay/connection_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,7 @@

#include "lib/netplay/net_result.h"

#if defined WZ_OS_UNIX
# include <netdb.h>
#elif defined WZ_OS_WIN
# include <ws2tcpip.h>
#endif

typedef struct addrinfo SocketAddress;

/// <summary>
/// Opaque class representing abstract connection address to use with various
Expand All @@ -50,23 +44,7 @@ typedef struct addrinfo SocketAddress;
/// New conversion routines should be introduced for other network backends,
/// if deemed necessary.
/// </summary>
class ConnectionAddress
struct IConnectionAddress
{
public:

ConnectionAddress();
ConnectionAddress(ConnectionAddress&&);
ConnectionAddress(const ConnectionAddress&) = delete;
~ConnectionAddress();

static net::result<ConnectionAddress> parse(const char* hostname, uint16_t port);
static net::result<ConnectionAddress> 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<Impl> mPimpl_;
virtual ~IConnectionAddress() = default;
};
4 changes: 2 additions & 2 deletions lib/netplay/netplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -4664,7 +4664,7 @@ bool NETenumerateGames(const std::function<bool (const GAMESTRUCT& game)>& 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();
Expand Down
32 changes: 32 additions & 0 deletions lib/netplay/tcp/tcp_connection_address.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
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

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / Fedora :LATEST [GCC]

#pragma once in main file [-Werror]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / Alpine :LATEST [GCC]

#pragma once in main file [-Werror]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / Arch :LATEST [Clang]

#pragma once in main file [-Werror,-Wpragma-once-outside-header]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / Arch :LATEST [GCC]

#pragma once in main file [-Werror]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / Fedora :LATEST [GCC -m32]

#pragma once in main file [-Werror]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04 [GCC]

#pragma once in main file [-Werror]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04 [Clang]

#pragma once in main file [-Werror,-Wpragma-once-outside-header]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 20.04 [GCC]

#pragma once in main file [-Werror]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 24.04 [Clang]

#pragma once in main file [-Werror,-Wpragma-once-outside-header]

Check warning on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / wasm32

#pragma once in main file [-Wpragma-once-outside-header]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / arm64 [LLVM_MINGW]

#pragma once in main file [-Werror,-Wpragma-once-outside-header]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / x86 [LLVM_MINGW]

#pragma once in main file [-Werror,-Wpragma-once-outside-header]

Check failure on line 17 in lib/netplay/tcp/tcp_connection_address.cpp

View workflow job for this annotation

GitHub Actions / x64 [LLVM_MINGW]

#pragma once in main file [-Werror,-Wpragma-once-outside-header]

#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_);
}
43 changes: 43 additions & 0 deletions lib/netplay/tcp/tcp_connection_address.h
Original file line number Diff line number Diff line change
@@ -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 <netdb.h>
#elif defined WZ_OS_WIN
# include <ws2tcpip.h>
#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_;
};
20 changes: 16 additions & 4 deletions lib/netplay/tcp/tcp_connection_provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -40,9 +41,14 @@ void TCPConnectionProvider::shutdown()
SOCKETshutdown();
}

net::result<ConnectionAddress> TCPConnectionProvider::resolveHost(const char* host, uint16_t port)
net::result<std::unique_ptr<IConnectionAddress>> 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<TCPConnectionAddress>(resolved.value());
}

net::result<IListenSocket*> TCPConnectionProvider::openListenSocket(uint16_t port)
Expand All @@ -55,9 +61,15 @@ net::result<IListenSocket*> TCPConnectionProvider::openListenSocket(uint16_t por
return new TCPListenSocket(res.value());
}

net::result<IClientConnection*> TCPConnectionProvider::openClientConnectionAny(const ConnectionAddress& addr, unsigned timeout)
net::result<IClientConnection*> TCPConnectionProvider::openClientConnectionAny(const IConnectionAddress& addr, unsigned timeout)
{
const auto* rawAddr = addr.asRawSocketAddress();
const auto* tcpAddr = dynamic_cast<const TCPConnectionAddress*>(&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())
{
Expand Down
4 changes: 2 additions & 2 deletions lib/netplay/tcp/tcp_connection_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ class TCPConnectionProvider final : public WzConnectionProvider
virtual void initialize() override;
virtual void shutdown() override;

virtual net::result<ConnectionAddress> resolveHost(const char* host, uint16_t port) override;
virtual net::result<std::unique_ptr<IConnectionAddress>> resolveHost(const char* host, uint16_t port) override;

virtual net::result<IListenSocket*> openListenSocket(uint16_t port) override;

virtual net::result<IClientConnection*> openClientConnectionAny(const ConnectionAddress& addr, unsigned timeout) override;
virtual net::result<IClientConnection*> openClientConnectionAny(const IConnectionAddress& addr, unsigned timeout) override;
virtual bool openClientConnectionAsync(const std::string& host, uint32_t port, OpenConnectionToHostResultCallback callback) override;

virtual IConnectionPollGroup* newConnectionPollGroup() override;
Expand Down
6 changes: 4 additions & 2 deletions lib/netplay/wz_connection_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#pragma once

#include <stdint.h>
#include <memory>

#include "lib/netplay/connection_address.h"
#include "lib/netplay/net_result.h"
Expand All @@ -28,6 +29,7 @@
class IListenSocket;
class IClientConnection;
class IConnectionPollGroup;
struct IConnectionAddress;

/// <summary>
/// Abstraction layer to facilitate creating client/server connections and
Expand Down Expand Up @@ -57,7 +59,7 @@ class WzConnectionProvider
/// Resolve host + port combination and return an opaque `ConnectionAddress` handle
/// representing the resolved network address.
/// </summary>
virtual net::result<ConnectionAddress> resolveHost(const char* host, uint16_t port) = 0;
virtual net::result<std::unique_ptr<IConnectionAddress>> resolveHost(const char* host, uint16_t port) = 0;
/// <summary>
/// Open a listening socket bound to a specified local port.
/// </summary>
Expand All @@ -68,7 +70,7 @@ class WzConnectionProvider
/// </summary>
/// <param name="addr">Connection address to bind the client connection to.</param>
/// <param name="timeout">Timeout in milliseconds.</param>
virtual net::result<IClientConnection*> openClientConnectionAny(const ConnectionAddress& addr, unsigned timeout) = 0;
virtual net::result<IClientConnection*> openClientConnectionAny(const IConnectionAddress& addr, unsigned timeout) = 0;
/// <summary>
/// Async variant of `openClientConnectionAny()`.
/// </summary>
Expand Down
3 changes: 1 addition & 2 deletions po/POTFILES.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 7568a5c

Please sign in to comment.