1
0
Fork 0

Fix: as client, try to reconnect more than once on server restart

pull/12070/head
Patric Stout 2024-02-11 22:53:56 +01:00
parent fa6f270f23
commit dc73aa50dd
7 changed files with 40 additions and 18 deletions

View File

@ -2640,6 +2640,7 @@ STR_NETWORK_MESSAGE_GIVE_MONEY :*** {0:RAW_STRI
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}The server closed the session
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}The server is restarting...{}Please wait...
STR_NETWORK_MESSAGE_KICKED :*** {RAW_STRING} was kicked. Reason: ({RAW_STRING})
STR_NETWORK_MESSAGE_SERVER_REBOOT_REJOIN_FAILED :{WHITE}Failed to reconnect to server
STR_NETWORK_ERROR_COORDINATOR_REGISTRATION_FAILED :{WHITE}Server registration failed
STR_NETWORK_ERROR_COORDINATOR_REUSE_OF_INVITE_CODE :{WHITE}Another server with the same invite-code registered itself. Switching to "local" game-type.

View File

@ -74,6 +74,8 @@ static const uint NETWORK_TOKEN_LENGTH = 64; ///< The m
static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF
static const uint32_t NETWORK_RECONNECT_ATTEMPTS = 8; ///< How many attempts before we give up reconnecting.
/**
* Maximum number of GRFs that can be sent.
*

View File

@ -64,7 +64,9 @@ bool _is_network_server; ///< Does this client wants to be a network-server?
NetworkCompanyState *_network_company_states = nullptr; ///< Statistics about some companies.
ClientID _network_own_client_id; ///< Our client identifier.
ClientID _redirect_console_to_client; ///< If not invalid, redirect the console output to a client.
uint8_t _network_reconnect; ///< Reconnect timeout
uint32_t _network_reconnect_attempts = 0; ///< How many attempts to reconnect left.
std::chrono::seconds _network_reconnect_backoff = {}; ///< How much time to wait for the next reconnect attempt.
std::chrono::steady_clock::time_point _network_reconnect = {}; ///< The time when to attempt another reconnect.
StringList _network_bind_list; ///< The addresses to bind on.
StringList _network_host_list; ///< The servers we know.
StringList _network_ban_list; ///< The banned clients.
@ -619,8 +621,6 @@ static void NetworkInitialize(bool close_admins = true)
_sync_frame = 0;
_network_first_time = true;
_network_reconnect = 0;
}
/** Non blocking connection to query servers for their game info. */
@ -738,7 +738,9 @@ public:
{
Debug(net, 9, "Client::OnFailure(): connection_string={}", this->connection_string);
ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION);
if (_network_reconnect_attempts == 0) {
ShowNetworkError(STR_NETWORK_ERROR_NOCONNECTION);
}
}
void OnConnect(SOCKET s) override

View File

@ -344,6 +344,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendJoin()
_network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
_network_reconnect_attempts = 0;
auto p = std::make_unique<Packet>(PACKET_CLIENT_JOIN);
p->Send_string(GetNetworkRevisionString());
p->Send_uint32(_openttd_newgrf_version);
@ -1124,14 +1126,10 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEWGAME(Packet
{
Debug(net, 9, "Client::Receive_SERVER_NEWGAME()");
/* Only when we're trying to join we really
* care about the server shutting down. */
if (this->status >= STATUS_JOIN) {
/* To throttle the reconnects a bit, every clients waits its
* Client ID modulo 16 + 1 (value 0 means no reconnect).
* This way reconnects should be spread out a bit. */
_network_reconnect = _network_own_client_id % 16 + 1;
ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT, INVALID_STRING_ID, WL_CRITICAL);
_network_reconnect_attempts = NETWORK_RECONNECT_ATTEMPTS;
_network_reconnect_backoff = std::chrono::seconds(1);
_network_reconnect = std::chrono::steady_clock::now() + _network_reconnect_backoff;
}
if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave();

View File

@ -28,7 +28,9 @@ extern NetworkCompanyState *_network_company_states;
extern ClientID _network_own_client_id;
extern ClientID _redirect_console_to_client;
extern uint8_t _network_reconnect;
extern uint32_t _network_reconnect_attempts;
extern std::chrono::seconds _network_reconnect_backoff;
extern std::chrono::steady_clock::time_point _network_reconnect;
extern StringList _network_bind_list;
extern StringList _network_host_list;
extern StringList _network_ban_list;

View File

@ -91,8 +91,6 @@ extern std::string _network_server_invite_code;
/* Variable available for clients. */
extern std::string _network_server_name;
extern uint8_t _network_reconnect;
extern CompanyMask _network_company_passworded;
void NetworkQueryServer(const std::string &connection_string);

View File

@ -1598,11 +1598,30 @@ void GameLoop()
/* Multiplayer */
NetworkGameLoop();
} else {
if (_network_reconnect > 0 && --_network_reconnect == 0) {
/* This means that we want to reconnect to the last host
* We do this here, because it means that the network is really closed */
NetworkClientConnectGame(_settings_client.network.last_joined, COMPANY_SPECTATOR);
if (_network_reconnect_attempts > 0 && std::chrono::steady_clock::now() > _network_reconnect) {
Debug(net, 3, "Reconnect attempt #{}", _network_reconnect_attempts);
_network_reconnect_attempts--;
_network_reconnect_backoff = std::min(_network_reconnect_backoff * 2, std::chrono::seconds(30));
_network_reconnect = std::chrono::steady_clock::now() + _network_reconnect_backoff;
if (_network_reconnect_attempts == 0) {
ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT_REJOIN_FAILED, INVALID_STRING_ID, WL_ERROR);
} else {
/* Show that we are reconnecting the first time we do an attempt.
* We have to do it this late, as switching to the main menu closes
* all errors (except critical, but this isn't critical). */
if (_network_reconnect_attempts == NETWORK_RECONNECT_ATTEMPTS - 1) {
ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT, INVALID_STRING_ID, WL_ERROR);
}
/* If the AskRelay window is open, don't start a new connect. */
if (FindWindowByClass(WC_NETWORK_ASK_RELAY) == nullptr) {
NetworkClientConnectGame(_settings_client.network.last_joined, COMPANY_SPECTATOR);
}
}
}
/* Singleplayer */
StateGameLoop();
}