Skip to content

Commit ca83611

Browse files
committed
netplay: introduce inheritance chain for connection address objects
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 <pavel.al.solodovnikov@gmail.com>
1 parent 74aaceb commit ca83611

8 files changed

+105
-99
lines changed

lib/netplay/connection_address.cpp

Lines changed: 0 additions & 65 deletions
This file was deleted.

lib/netplay/connection_address.h

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,7 @@
2626

2727
#include "lib/netplay/net_result.h"
2828

29-
#if defined WZ_OS_UNIX
30-
# include <netdb.h>
31-
#elif defined WZ_OS_WIN
32-
# include <ws2tcpip.h>
33-
#endif
3429

35-
typedef struct addrinfo SocketAddress;
3630

3731
/// <summary>
3832
/// Opaque class representing abstract connection address to use with various
@@ -53,23 +47,7 @@ typedef struct addrinfo SocketAddress;
5347
/// New conversion routines should be introduced for other network backends,
5448
/// if deemed necessary.
5549
/// </summary>
56-
class ConnectionAddress
50+
struct IConnectionAddress
5751
{
58-
public:
59-
60-
ConnectionAddress();
61-
ConnectionAddress(ConnectionAddress&&);
62-
ConnectionAddress(const ConnectionAddress&) = delete;
63-
~ConnectionAddress();
64-
65-
static net::result<ConnectionAddress> parse(const char* hostname, uint16_t port);
66-
static net::result<ConnectionAddress> parse(const std::string& hostname, uint16_t port);
67-
68-
// NOTE: The lifetime of the returned `addrinfo` struct is bounded by the parent object's lifetime!
69-
const SocketAddress* asRawSocketAddress() const;
70-
71-
private:
72-
73-
struct Impl;
74-
std::unique_ptr<Impl> mPimpl_;
52+
virtual ~IConnectionAddress() = default;
7553
};

lib/netplay/netplay.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3484,7 +3484,7 @@ bool LobbyServerConnectionHandler::connect()
34843484
}
34853485

34863486
// try each address from resolveHost until we successfully connect.
3487-
auto sockResult = connProvider.openClientConnectionAny(hosts, 1500);
3487+
auto sockResult = connProvider.openClientConnectionAny(*hosts, 1500);
34883488

34893489
rs_socket = sockResult.value_or(nullptr);
34903490

@@ -4741,7 +4741,7 @@ bool NETenumerateGames(const std::function<bool (const GAMESTRUCT& game)>& handl
47414741
return false;
47424742
}
47434743
const auto& hosts = hostsResult.value();
4744-
auto sockResult = connProvider.openClientConnectionAny(hosts, 15000);
4744+
auto sockResult = connProvider.openClientConnectionAny(*hosts, 15000);
47454745

47464746
if (!sockResult.has_value()) {
47474747
const auto sockErrMsg = sockResult.error().message();
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
This file is part of Warzone 2100.
3+
Copyright (C) 2024 Warzone 2100 Project
4+
5+
Warzone 2100 is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 2 of the License, or
8+
(at your option) any later version.
9+
10+
Warzone 2100 is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with Warzone 2100; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include "lib/netplay/tcp/tcp_connection_address.h"
21+
22+
#include "lib/netplay/tcp/netsocket.h" // for `freeaddrinfo`
23+
#include "lib/framework/frame.h" // for `ASSERT`
24+
25+
TCPConnectionAddress::TCPConnectionAddress(SocketAddress* addr)
26+
: addr_(addr)
27+
{}
28+
29+
TCPConnectionAddress::~TCPConnectionAddress()
30+
{
31+
ASSERT(addr_ != nullptr, "Invalid addrinfo stored in the connection address");
32+
freeaddrinfo(addr_);
33+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
This file is part of Warzone 2100.
3+
Copyright (C) 2024 Warzone 2100 Project
4+
5+
Warzone 2100 is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 2 of the License, or
8+
(at your option) any later version.
9+
10+
Warzone 2100 is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with Warzone 2100; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#pragma once
21+
22+
#include "lib/netplay/connection_address.h"
23+
24+
#if defined WZ_OS_UNIX
25+
# include <netdb.h>
26+
#elif defined WZ_OS_WIN
27+
# include <ws2tcpip.h>
28+
#endif
29+
30+
typedef struct addrinfo SocketAddress;
31+
32+
class TCPConnectionAddress : public IConnectionAddress
33+
{
34+
public:
35+
36+
/// Assumes ownership of `addr`
37+
explicit TCPConnectionAddress(SocketAddress* addr);
38+
virtual ~TCPConnectionAddress() override;
39+
40+
// NOTE: The lifetime of the returned `addrinfo` struct is bounded by the parent object's lifetime!
41+
const SocketAddress* asRawSocketAddress() const { return addr_; }
42+
43+
private:
44+
45+
SocketAddress* addr_;
46+
};

lib/netplay/tcp/tcp_connection_provider.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "tcp_connection_provider.h"
2121

2222
#include "lib/netplay/tcp/netsocket.h"
23+
#include "lib/netplay/tcp/tcp_connection_address.h"
2324
#include "lib/netplay/tcp/tcp_connection_poll_group.h"
2425
#include "lib/netplay/tcp/tcp_client_connection.h"
2526
#include "lib/netplay/tcp/tcp_listen_socket.h"
@@ -40,9 +41,14 @@ void TCPConnectionProvider::shutdown()
4041
SOCKETshutdown();
4142
}
4243

43-
net::result<ConnectionAddress> TCPConnectionProvider::resolveHost(const char* host, uint16_t port)
44+
net::result<std::unique_ptr<IConnectionAddress>> TCPConnectionProvider::resolveHost(const char* host, uint16_t port)
4445
{
45-
return ConnectionAddress::parse(host, port);
46+
auto resolved = tcp::resolveHost(host, port);
47+
if (!resolved.has_value())
48+
{
49+
return tl::make_unexpected(resolved.error());
50+
}
51+
return std::make_unique<TCPConnectionAddress>(resolved.value());
4652
}
4753

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

58-
net::result<IClientConnection*> TCPConnectionProvider::openClientConnectionAny(const ConnectionAddress& addr, unsigned timeout)
64+
net::result<IClientConnection*> TCPConnectionProvider::openClientConnectionAny(const IConnectionAddress& addr, unsigned timeout)
5965
{
60-
const auto* rawAddr = addr.asRawSocketAddress();
66+
const auto* tcpAddr = dynamic_cast<const TCPConnectionAddress*>(&addr);
67+
ASSERT(tcpAddr != nullptr, "Expected TCPConnectionAddress instance");
68+
if (!tcpAddr)
69+
{
70+
throw std::runtime_error("Expected TCPConnectionAddress instance");
71+
}
72+
const auto* rawAddr = tcpAddr->asRawSocketAddress();
6173
auto res = socketOpenAny(rawAddr, timeout);
6274
if (!res.has_value())
6375
{

lib/netplay/tcp/tcp_connection_provider.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ class TCPConnectionProvider final : public WzConnectionProvider
3535
virtual void initialize() override;
3636
virtual void shutdown() override;
3737

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

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

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

4545
virtual IConnectionPollGroup* newConnectionPollGroup() override;

lib/netplay/wz_connection_provider.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#pragma once
2121

2222
#include <stdint.h>
23+
#include <memory>
2324

2425
#include "lib/netplay/connection_address.h"
2526
#include "lib/netplay/net_result.h"
@@ -28,6 +29,7 @@
2829
class IListenSocket;
2930
class IClientConnection;
3031
class IConnectionPollGroup;
32+
struct IConnectionAddress;
3133

3234
/// <summary>
3335
/// Abstraction layer to facilitate creating client/server connections and
@@ -57,7 +59,7 @@ class WzConnectionProvider
5759
/// Resolve host + port combination and return an opaque `ConnectionAddress` handle
5860
/// representing the resolved network address.
5961
/// </summary>
60-
virtual net::result<ConnectionAddress> resolveHost(const char* host, uint16_t port) = 0;
62+
virtual net::result<std::unique_ptr<IConnectionAddress>> resolveHost(const char* host, uint16_t port) = 0;
6163
/// <summary>
6264
/// Open a listening socket bound to a specified local port.
6365
/// </summary>
@@ -68,7 +70,7 @@ class WzConnectionProvider
6870
/// </summary>
6971
/// <param name="addr">Connection address to bind the client connection to.</param>
7072
/// <param name="timeout">Timeout in milliseconds.</param>
71-
virtual net::result<IClientConnection*> openClientConnectionAny(const ConnectionAddress& addr, unsigned timeout) = 0;
73+
virtual net::result<IClientConnection*> openClientConnectionAny(const IConnectionAddress& addr, unsigned timeout) = 0;
7274
/// <summary>
7375
/// Async variant of `openClientConnectionAny()`.
7476
/// </summary>

0 commit comments

Comments
 (0)