Merge tag '1.11.1' into 1.11
This commit is contained in:
@@ -239,7 +239,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));
|
||||
|
||||
|
||||
@@ -74,19 +74,12 @@ uint32 _sync_seed_2; ///< Second part of the seed.
|
||||
#endif
|
||||
uint32 _sync_frame; ///< The frame to perform the sync check.
|
||||
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;
|
||||
|
||||
@@ -724,7 +717,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;
|
||||
@@ -1060,7 +1053,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();
|
||||
|
||||
@@ -500,7 +500,9 @@ public:
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_NG_MATRIX:
|
||||
resize->height = SETTING_BUTTON_HEIGHT;
|
||||
resize->height = WD_MATRIX_TOP + std::max(GetSpriteSize(SPR_BLOT).height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_BOTTOM;
|
||||
resize->height = GetMinSizing(NWST_STEP, resize->height);
|
||||
fill->height = resize->height;
|
||||
size->height = 5 * resize->height;
|
||||
break;
|
||||
|
||||
@@ -955,7 +957,7 @@ static const NWidgetPart _nested_network_game_widgets[] = {
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_DETAILS),
|
||||
NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(5, 5, 5),
|
||||
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NG_DETAILS_SPACER), SetMinimalSize(140, 155), SetResize(0, 1), SetFill(1, 1), // Make sure it's at least this wide
|
||||
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NG_DETAILS_SPACER), SetMinimalSize(140, 0), SetMinimalTextLines(15, 24 + WD_PAR_VSEP_NORMAL), SetResize(0, 1), SetFill(1, 1), // Make sure it's at least this wide
|
||||
NWidget(NWID_HORIZONTAL, NC_NONE), SetPIP(5, 5, 5),
|
||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NG_NEWGRF_MISSING_SEL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NEWGRF_MISSING), SetFill(1, 0), SetDataTip(STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_BUTTON, STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_TOOLTIP),
|
||||
|
||||
@@ -126,11 +126,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);
|
||||
|
||||
@@ -456,7 +456,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err
|
||||
}
|
||||
|
||||
for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
|
||||
if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
|
||||
if (new_cs->status >= STATUS_AUTHORIZED && new_cs != this) {
|
||||
/* Some errors we filter to a more general error. Clients don't have to know the real
|
||||
* reason a joining failed. */
|
||||
if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION) {
|
||||
@@ -549,7 +549,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendWelcome()
|
||||
|
||||
/* Transmit info about all the active clients */
|
||||
for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
|
||||
if (new_cs != this && new_cs->status > STATUS_AUTHORIZED) {
|
||||
if (new_cs != this && new_cs->status >= STATUS_AUTHORIZED) {
|
||||
this->SendClientInfo(new_cs->GetInfo());
|
||||
}
|
||||
}
|
||||
@@ -1068,7 +1068,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MAP_OK(Packet *
|
||||
this->last_frame_server = _frame_counter;
|
||||
|
||||
for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
|
||||
if (new_cs->status > STATUS_AUTHORIZED) {
|
||||
if (new_cs->status >= STATUS_AUTHORIZED) {
|
||||
new_cs->SendClientInfo(this->GetInfo());
|
||||
new_cs->SendJoin(this->client_id);
|
||||
}
|
||||
@@ -1178,7 +1178,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p
|
||||
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
|
||||
|
||||
for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
|
||||
if (new_cs->status > STATUS_AUTHORIZED) {
|
||||
if (new_cs->status >= STATUS_AUTHORIZED) {
|
||||
new_cs->SendErrorQuit(this->client_id, errorno);
|
||||
}
|
||||
}
|
||||
@@ -1204,7 +1204,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet *p)
|
||||
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
|
||||
|
||||
for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
|
||||
if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
|
||||
if (new_cs->status >= STATUS_AUTHORIZED && new_cs != this) {
|
||||
new_cs->SendQuit(this->client_id);
|
||||
}
|
||||
}
|
||||
@@ -1607,7 +1607,9 @@ void NetworkUpdateClientInfo(ClientID client_id)
|
||||
DEBUG(desync, 1, "client: %08x; %02x; %02x; %04x", _date, _date_fract, (int)ci->client_playas, client_id);
|
||||
|
||||
for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
|
||||
cs->SendClientInfo(ci);
|
||||
if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
|
||||
cs->SendClientInfo(ci);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkAdminClientUpdate(ci);
|
||||
|
||||
+68
-35
@@ -33,9 +33,6 @@
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Mutex for all out threaded udp resolution and such. */
|
||||
static std::mutex _network_udp_mutex;
|
||||
|
||||
/** Session key to register ourselves to the master server */
|
||||
static uint64 _session_key = 0;
|
||||
|
||||
@@ -43,9 +40,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
|
||||
|
||||
/**
|
||||
* Helper function doing the actual work for querying the server.
|
||||
@@ -63,11 +96,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(PACKET_UDP_CLIENT_FIND_SERVER);
|
||||
if (_udp_client_socket != nullptr) _udp_client_socket->SendPacket(&p, &address);
|
||||
if (_udp_client.socket != nullptr) _udp_client.socket->SendPacket(&p, &address);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,7 +508,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", out_addr.GetAddressAsString().c_str());
|
||||
}
|
||||
@@ -488,7 +522,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
|
||||
}
|
||||
|
||||
@@ -508,8 +542,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,8 +594,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -603,40 +637,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;
|
||||
@@ -646,13 +681,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--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user