Merge branch 'master' into jgrpp

# Conflicts:
#	src/lang/french.txt
#	src/network/network_udp.cpp
This commit is contained in:
Jonathan G Rennison
2021-04-12 22:59:30 +01:00
23 changed files with 174 additions and 81 deletions

View File

@@ -237,7 +237,18 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList *
strecpy(this->hostname, fam == AF_INET ? "0.0.0.0" : "::", lastof(this->hostname));
}
static bool _resolve_timeout_error_message_shown = false;
auto start = std::chrono::steady_clock::now();
int e = getaddrinfo(StrEmpty(this->hostname) ? nullptr : this->hostname, port_name, &hints, &ai);
auto end = std::chrono::steady_clock::now();
std::chrono::seconds duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);
if (!_resolve_timeout_error_message_shown && duration >= std::chrono::seconds(5)) {
DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s took %i seconds",
this->hostname, port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), (int)duration.count());
DEBUG(net, 0, " this is likely an issue in the DNS name resolver's configuration causing it to time out");
_resolve_timeout_error_message_shown = true;
}
if (reset_hostname) strecpy(this->hostname, "", lastof(this->hostname));

View File

@@ -80,19 +80,12 @@ Date _last_sync_date; ///< The game date of the last successfull
DateFract _last_sync_date_fract; ///< "
uint8 _last_sync_tick_skip_counter; ///< "
bool _network_first_time; ///< Whether we have finished joining or not.
bool _network_udp_server; ///< Is the UDP server started?
uint16 _network_udp_broadcast; ///< Timeout for the UDP broadcasts.
uint8 _network_advertise_retries; ///< The number of advertisement retries we did.
CompanyMask _network_company_passworded; ///< Bitmask of the password status of all companies.
/* Check whether NETWORK_NUM_LANDSCAPES is still in sync with NUM_LANDSCAPE */
static_assert((int)NETWORK_NUM_LANDSCAPES == (int)NUM_LANDSCAPE);
static_assert((int)NETWORK_COMPANY_NAME_LENGTH == MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH);
extern NetworkUDPSocketHandler *_udp_client_socket; ///< udp client socket
extern NetworkUDPSocketHandler *_udp_server_socket; ///< udp server socket
extern NetworkUDPSocketHandler *_udp_master_socket; ///< udp master socket
/** The amount of clients connected */
byte _network_clients_connected = 0;
@@ -754,7 +747,7 @@ bool NetworkServerStart()
/* Try to start UDP-server */
DEBUG(net, 1, "starting listeners for incoming server queries");
_network_udp_server = _udp_server_socket->Listen();
NetworkUDPServerListen();
_network_company_states = CallocT<NetworkCompanyState>(MAX_COMPANIES);
_network_server = true;
@@ -1100,7 +1093,6 @@ void NetworkStartUp()
_network_available = NetworkCoreInitialize();
_network_dedicated = false;
_network_need_advertise = true;
_network_advertise_retries = 0;
/* Generate an server id when there is none yet */
if (StrEmpty(_settings_client.network.network_id)) NetworkGenerateServerId();

View File

@@ -130,11 +130,6 @@ extern uint32 _network_join_bytes_total;
extern uint8 _network_reconnect;
extern bool _network_udp_server;
extern uint16 _network_udp_broadcast;
extern uint8 _network_advertise_retries;
extern CompanyMask _network_company_passworded;
void NetworkTCPQueryServer(NetworkAddress address);

View File

@@ -51,9 +51,45 @@ static const std::chrono::minutes ADVERTISE_NORMAL_INTERVAL(15); ///< interval b
static const std::chrono::seconds ADVERTISE_RETRY_INTERVAL(10); ///< re-advertise when no response after this amount of time.
static const uint32 ADVERTISE_RETRY_TIMES = 3; ///< give up re-advertising after this much failed retries
NetworkUDPSocketHandler *_udp_client_socket = nullptr; ///< udp client socket
NetworkUDPSocketHandler *_udp_server_socket = nullptr; ///< udp server socket
NetworkUDPSocketHandler *_udp_master_socket = nullptr; ///< udp master socket
static bool _network_udp_server; ///< Is the UDP server started?
static uint16 _network_udp_broadcast; ///< Timeout for the UDP broadcasts.
static uint8 _network_advertise_retries; ///< The number of advertisement retries we did.
/** Some information about a socket, which exists before the actual socket has been created to provide locking and the likes. */
struct UDPSocket {
const std::string name; ///< The name of the socket.
std::mutex mutex; ///< Mutex for everything that (indirectly) touches the sockets within the handler.
NetworkUDPSocketHandler *socket; ///< The actual socket, which may be nullptr when not initialized yet.
std::atomic<int> receive_iterations_locked; ///< The number of receive iterations the mutex was locked.
UDPSocket(const std::string &name_) : name(name_), socket(nullptr) {}
void Close()
{
std::lock_guard<std::mutex> lock(mutex);
socket->Close();
delete socket;
socket = nullptr;
}
void ReceivePackets()
{
std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
if (!lock.try_lock()) {
if (++receive_iterations_locked % 32 == 0) {
DEBUG(net, 0, "[udp] %s background UDP loop processing appears to be blocked. Your OS may be low on UDP send buffers.", name.c_str());
}
return;
}
receive_iterations_locked.store(0);
socket->ReceivePackets();
}
};
static UDPSocket _udp_client("Client"); ///< udp client socket
static UDPSocket _udp_server("Server"); ///< udp server socket
static UDPSocket _udp_master("Master"); ///< udp master socket
static Packet PrepareUdpClientFindServerPacket()
{
@@ -80,11 +116,11 @@ static void DoNetworkUDPQueryServer(NetworkAddress &address, bool needs_mutex, b
item->manually = manually;
NetworkGameListAddItemDelayed(item);
std::unique_lock<std::mutex> lock(_network_udp_mutex, std::defer_lock);
std::unique_lock<std::mutex> lock(_udp_client.mutex, std::defer_lock);
if (needs_mutex) lock.lock();
/* Init the packet */
Packet p = PrepareUdpClientFindServerPacket();
if (_udp_client_socket != nullptr) _udp_client_socket->SendPacket(&p, &address);
if (_udp_client.socket != nullptr) _udp_client.socket->SendPacket(&p, &address);
}
/**
@@ -560,7 +596,8 @@ void NetworkUDPQueryMasterServer()
p.Send_uint8(NETWORK_MASTER_SERVER_VERSION);
p.Send_uint8(SLT_AUTODETECT);
_udp_client_socket->SendPacket(&p, &out_addr, true);
std::lock_guard<std::mutex> lock(_udp_client.mutex);
_udp_client.socket->SendPacket(&p, &out_addr, true);
DEBUG(net, 2, "[udp] master server queried at %s", NetworkAddressDumper().GetAddressAsString(&out_addr));
}
@@ -573,7 +610,7 @@ void NetworkUDPSearchGame()
DEBUG(net, 0, "[udp] searching server");
NetworkUDPBroadCast(_udp_client_socket);
NetworkUDPBroadCast(_udp_client.socket);
_network_udp_broadcast = 300; // Stay searching for 300 ticks
}
@@ -593,8 +630,8 @@ static void NetworkUDPRemoveAdvertiseThread()
p.Send_uint8 (NETWORK_MASTER_SERVER_VERSION);
p.Send_uint16(_settings_client.network.server_port);
std::lock_guard<std::mutex> lock(_network_udp_mutex);
if (_udp_master_socket != nullptr) _udp_master_socket->SendPacket(&p, &out_addr, true);
std::lock_guard<std::mutex> lock(_udp_master.mutex);
if (_udp_master.socket != nullptr) _udp_master.socket->SendPacket(&p, &out_addr, true);
}
/**
@@ -645,8 +682,8 @@ static void NetworkUDPAdvertiseThread()
p.Send_uint16(_settings_client.network.server_port);
p.Send_uint64(_session_key);
std::lock_guard<std::mutex> lock(_network_udp_mutex);
if (_udp_master_socket != nullptr) _udp_master_socket->SendPacket(&p, &out_addr, true);
std::lock_guard<std::mutex> lock(_udp_master.mutex);
if (_udp_master.socket != nullptr) _udp_master.socket->SendPacket(&p, &out_addr, true);
}
/**
@@ -688,40 +725,41 @@ void NetworkUDPAdvertise()
void NetworkUDPInitialize()
{
/* If not closed, then do it. */
if (_udp_server_socket != nullptr) NetworkUDPClose();
if (_udp_server.socket != nullptr) NetworkUDPClose();
DEBUG(net, 1, "[udp] initializing listeners");
assert(_udp_client_socket == nullptr && _udp_server_socket == nullptr && _udp_master_socket == nullptr);
assert(_udp_client.socket == nullptr && _udp_server.socket == nullptr && _udp_master.socket == nullptr);
std::lock_guard<std::mutex> lock(_network_udp_mutex);
std::scoped_lock lock(_udp_client.mutex, _udp_server.mutex, _udp_master.mutex);
_udp_client_socket = new ClientNetworkUDPSocketHandler();
_udp_client.socket = new ClientNetworkUDPSocketHandler();
NetworkAddressList server;
GetBindAddresses(&server, _settings_client.network.server_port);
_udp_server_socket = new ServerNetworkUDPSocketHandler(&server);
_udp_server.socket = new ServerNetworkUDPSocketHandler(&server);
server.clear();
GetBindAddresses(&server, 0);
_udp_master_socket = new MasterNetworkUDPSocketHandler(&server);
_udp_master.socket = new MasterNetworkUDPSocketHandler(&server);
_network_udp_server = false;
_network_udp_broadcast = 0;
_network_advertise_retries = 0;
}
/** Start the listening of the UDP server component. */
void NetworkUDPServerListen()
{
std::lock_guard<std::mutex> lock(_udp_server.mutex);
_network_udp_server = _udp_server.socket->Listen();
}
/** Close all UDP related stuff. */
void NetworkUDPClose()
{
std::lock_guard<std::mutex> lock(_network_udp_mutex);
_udp_server_socket->Close();
_udp_master_socket->Close();
_udp_client_socket->Close();
delete _udp_client_socket;
delete _udp_server_socket;
delete _udp_master_socket;
_udp_client_socket = nullptr;
_udp_server_socket = nullptr;
_udp_master_socket = nullptr;
_udp_client.Close();
_udp_server.Close();
_udp_master.Close();
_network_udp_server = false;
_network_udp_broadcast = 0;
@@ -731,13 +769,11 @@ void NetworkUDPClose()
/** Receive the UDP packets. */
void NetworkBackgroundUDPLoop()
{
std::lock_guard<std::mutex> lock(_network_udp_mutex);
if (_network_udp_server) {
_udp_server_socket->ReceivePackets();
_udp_master_socket->ReceivePackets();
_udp_server.ReceivePackets();
_udp_master.ReceivePackets();
} else {
_udp_client_socket->ReceivePackets();
_udp_client.ReceivePackets();
if (_network_udp_broadcast > 0) _network_udp_broadcast--;
}
}

View File

@@ -19,6 +19,7 @@ void NetworkUDPQueryServer(NetworkAddress address, bool manually = false);
void NetworkUDPAdvertise();
void NetworkUDPRemoveAdvertise(bool blocking);
void NetworkUDPClose();
void NetworkUDPServerListen();
void NetworkBackgroundUDPLoop();
#endif /* NETWORK_UDP_H */