diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 8adff7a139..72ad4bf3ef 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1797,36 +1797,30 @@ void NetworkServer_Tick(bool send_frame) uint lag = NetworkCalculateLag(cs); switch (cs->status) { case NetworkClientSocket::STATUS_ACTIVE: - /* 1 lag-point per day */ - lag /= DAY_TICKS; - if (lag > 0) { - if (lag > 3) { - /* Client did still not report in after 4 game-day, drop him - * (that is, the 3 of above, + 1 before any lag is counted) */ - IConsolePrintF(CC_ERROR, cs->last_packet + 3 * DAY_TICKS * MILLISECONDS_PER_TICK > _realtime_tick ? - /* A packet was received in the last three game days, so the client is likely lagging behind. */ - "Client #%d is dropped because the client's game state is more than 4 game-days behind" : - /* No packet was received in the last three game days; sounds like a lost connection. */ - "Client #%d is dropped because the client did not respond for more than 4 game-days", - cs->client_id); - cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); - continue; - } + if (lag > _settings_client.network.max_lag_time) { + /* Client did still not report in within the specififed limit. */ + IConsolePrintF(CC_ERROR, cs->last_packet + lag * MILLISECONDS_PER_TICK > _realtime_tick ? + /* A packet was received in the last three game days, so the client is likely lagging behind. */ + "Client #%d is dropped because the client's game state is more than %d ticks behind" : + /* No packet was received in the last three game days; sounds like a lost connection. */ + "Client #%d is dropped because the client did not respond for more than %d ticks", + cs->client_id, lag); + cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); + continue; + } - /* Report once per time we detect the lag, and only when we - * received a packet in the last 2000 milliseconds. If we - * did not receive a packet, then the client is not just - * slow, but the connection is likely severed. Mentioning - * frame_freq is not useful in this case. */ - if (cs->lag_test == 0 && cs->last_packet + DAY_TICKS * MILLISECONDS_PER_TICK > _realtime_tick) { - IConsolePrintF(CC_WARNING,"[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id); - cs->lag_test = 1; - } - } else { - cs->lag_test = 0; + /* Report once per time we detect the lag, and only when we + * received a packet in the last 2000 milliseconds. If we + * did not receive a packet, then the client is not just + * slow, but the connection is likely severed. Mentioning + * frame_freq is not useful in this case. */ + if (lag > (uint)DAY_TICKS && cs->lag_test == 0 && cs->last_packet + 2000 > _realtime_tick) { + IConsolePrintF(CC_WARNING, "[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id); + cs->lag_test = 1; } - if (cs->last_frame_server - cs->last_token_frame >= 5 * DAY_TICKS) { - /* This is a bad client! It didn't send the right token back. */ + + if (cs->last_frame_server - cs->last_token_frame >= _settings_client.network.max_lag_time) { + /* This is a bad client! It didn't send the right token back within time. */ IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id); cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); continue; @@ -1838,8 +1832,8 @@ void NetworkServer_Tick(bool send_frame) case NetworkClientSocket::STATUS_AUTHORIZED: /* NewGRF check and authorized states should be handled almost instantly. * So give them some lee-way, likewise for the query with inactive. */ - if (lag > 4 * DAY_TICKS) { - IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->client_id, 4 * DAY_TICKS); + if (lag > _settings_client.network.max_init_time) { + IConsolePrintF(CC_ERROR, "Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->client_id, _settings_client.network.max_init_time); cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); continue; } @@ -1848,7 +1842,7 @@ void NetworkServer_Tick(bool send_frame) case NetworkClientSocket::STATUS_MAP: /* Downloading the map... this is the amount of time since starting the saving. */ if (lag > _settings_client.network.max_download_time) { - IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to download the map", cs->client_id, _settings_client.network.max_download_time); + IConsolePrintF(CC_ERROR, "Client #%d is dropped because it took longer than %d ticks to download the map", cs->client_id, _settings_client.network.max_download_time); cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); continue; } @@ -1858,7 +1852,7 @@ void NetworkServer_Tick(bool send_frame) case NetworkClientSocket::STATUS_PRE_ACTIVE: /* The map has been sent, so this is for loading the map and syncing up. */ if (lag > _settings_client.network.max_join_time) { - IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->client_id, _settings_client.network.max_join_time); + IConsolePrintF(CC_ERROR, "Client #%d is dropped because it took longer than %d ticks to join", cs->client_id, _settings_client.network.max_join_time); cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); continue; } @@ -1868,7 +1862,7 @@ void NetworkServer_Tick(bool send_frame) case NetworkClientSocket::STATUS_AUTH_COMPANY: /* These don't block? */ if (lag > _settings_client.network.max_password_time) { - IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d to enter the password", cs->client_id, _settings_client.network.max_password_time); + IConsolePrintF(CC_ERROR, "Client #%d is dropped because it took longer than %d ticks to enter the password", cs->client_id, _settings_client.network.max_password_time); cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD); continue; } diff --git a/src/settings_type.h b/src/settings_type.h index 4f8f36a075..1f91a542a7 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -172,9 +172,11 @@ struct NetworkSettings { uint16 max_commands_in_queue; ///< how many commands may there be in the incoming queue before dropping the connection? uint16 bytes_per_frame; ///< how many bytes may, over a long period, be received per frame? uint16 bytes_per_frame_burst; ///< how many bytes may, over a short period, be received? - uint16 max_join_time; ///< maximum amount of time, in game ticks, a client may take to join + uint16 max_init_time; ///< maximum amount of time, in game ticks, a client may take to initiate joining + uint16 max_join_time; ///< maximum amount of time, in game ticks, a client may take to sync up during joining uint16 max_download_time; ///< maximum amount of time, in game ticks, a client may take to download the map uint16 max_password_time; ///< maximum amount of time, in game ticks, a client may take to enter the password + uint16 max_lag_time; ///< maximum amount of time, in game ticks, a client may be lagging behind the server bool pause_on_join; ///< pause the game when people join uint16 server_port; ///< port the server listens on uint16 server_admin_port; ///< port the server listens on for the admin network diff --git a/src/table/settings.ini b/src/table/settings.ini index fddd034be2..aec498f820 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -2643,6 +2643,16 @@ def = 256 min = 1 max = 65535 +[SDTC_VAR] +ifdef = ENABLE_NETWORK +var = network.max_init_time +type = SLE_UINT16 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_NETWORK_ONLY +def = 100 +min = 0 +max = 32000 + [SDTC_VAR] ifdef = ENABLE_NETWORK var = network.max_join_time @@ -2673,6 +2683,16 @@ def = 2000 min = 0 max = 32000 +[SDTC_VAR] +ifdef = ENABLE_NETWORK +var = network.max_lag_time +type = SLE_UINT16 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_NETWORK_ONLY +def = 500 +min = 0 +max = 32000 + [SDTC_BOOL] ifdef = ENABLE_NETWORK var = network.pause_on_join