diff options
author | rubidium <rubidium@openttd.org> | 2012-01-06 21:49:06 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2012-01-06 21:49:06 +0000 |
commit | bddfcaef9520b68d28480c9f84a9bd8a586e01f3 (patch) | |
tree | c8e7e6b83f41797bb92efe10ba29b2a0d40d7883 | |
parent | 9d958ff581a4ca06912228812a89d087aa0dceb8 (diff) | |
download | openttd-bddfcaef9520b68d28480c9f84a9bd8a586e01f3.tar.xz |
(svn r23764) -Fix [FS#4955]: make default timeouts for certain states lower and configurable
-rw-r--r-- | src/lang/english.txt | 2 | ||||
-rw-r--r-- | src/network/network_client.cpp | 6 | ||||
-rw-r--r-- | src/network/network_server.cpp | 129 | ||||
-rw-r--r-- | src/network/network_type.h | 2 | ||||
-rw-r--r-- | src/settings_type.h | 2 | ||||
-rw-r--r-- | src/table/settings.ini | 20 |
6 files changed, 116 insertions, 45 deletions
diff --git a/src/lang/english.txt b/src/lang/english.txt index 7730f4ecd..744ffdcbf 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1799,6 +1799,8 @@ STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}You are STR_NETWORK_ERROR_KICKED :{WHITE}You were kicked out of the game STR_NETWORK_ERROR_CHEATER :{WHITE}Cheating is not allowed on this server STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}You were sending too many commands to the server +STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}You took too long to enter the password +STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Your computer took too long to join ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :general error diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 3de63a4e0..3a0f58b83 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -670,6 +670,12 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p case NETWORK_ERROR_TOO_MANY_COMMANDS: ShowErrorMessage(STR_NETWORK_ERROR_TOO_MANY_COMMANDS, INVALID_STRING_ID, WL_CRITICAL); break; + case NETWORK_ERROR_TIMEOUT_PASSWORD: + ShowErrorMessage(STR_NETWORK_ERROR_TIMEOUT_PASSWORD, INVALID_STRING_ID, WL_CRITICAL); + break; + case NETWORK_ERROR_TIMEOUT_COMPUTER: + ShowErrorMessage(STR_NETWORK_ERROR_TIMEOUT_COMPUTER, INVALID_STRING_ID, WL_CRITICAL); + break; default: ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL); } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 72f956240..8adff7a13 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1794,55 +1794,94 @@ void NetworkServer_Tick(bool send_frame) _settings_client.network.bytes_per_frame_burst); /* Check if the speed of the client is what we can expect from a client */ - if (cs->status == NetworkClientSocket::STATUS_ACTIVE) { - /* 1 lag-point per day */ - uint lag = NetworkCalculateLag(cs) / 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->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR); + 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; + } + + /* 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; + } + 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. */ + IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id); + cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); continue; } + break; - /* 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; + case NetworkClientSocket::STATUS_INACTIVE: + case NetworkClientSocket::STATUS_NEWGRFS_CHECK: + 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); + cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); + continue; } - } else { - cs->lag_test = 0; - } - 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. */ - IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id); - cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR); - continue; - } - } else if (cs->status == NetworkClientSocket::STATUS_PRE_ACTIVE) { - uint lag = NetworkCalculateLag(cs); - 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); - cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR); - continue; - } - } else if (cs->status == NetworkClientSocket::STATUS_INACTIVE) { - uint lag = NetworkCalculateLag(cs); - 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); - cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR); - continue; - } + break; + + 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); + cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); + continue; + } + break; + + case NetworkClientSocket::STATUS_DONE_MAP: + 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); + cs->SendError(NETWORK_ERROR_TIMEOUT_COMPUTER); + continue; + } + break; + + case NetworkClientSocket::STATUS_AUTH_GAME: + 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); + cs->SendError(NETWORK_ERROR_TIMEOUT_PASSWORD); + continue; + } + break; + + case NetworkClientSocket::STATUS_MAP_WAIT: + /* This is an internal state where we do not wait + * on the client to move to a different state. */ + break; + + case NetworkClientSocket::STATUS_END: + /* Bad server/code. */ + NOT_REACHED(); } if (cs->status >= NetworkClientSocket::STATUS_PRE_ACTIVE) { diff --git a/src/network/network_type.h b/src/network/network_type.h index ff29492b7..eff46a232 100644 --- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -122,6 +122,8 @@ enum NetworkErrorCode { NETWORK_ERROR_CHEATER, NETWORK_ERROR_FULL, NETWORK_ERROR_TOO_MANY_COMMANDS, + NETWORK_ERROR_TIMEOUT_PASSWORD, + NETWORK_ERROR_TIMEOUT_COMPUTER, }; #endif /* ENABLE_NETWORK */ diff --git a/src/settings_type.h b/src/settings_type.h index 541aad2fe..4f8f36a07 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -173,6 +173,8 @@ struct NetworkSettings { 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_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 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 3a834336a..fddd034be 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -2653,6 +2653,26 @@ def = 500 min = 0 max = 32000 +[SDTC_VAR] +ifdef = ENABLE_NETWORK +var = network.max_download_time +type = SLE_UINT16 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_NETWORK_ONLY +def = 1000 +min = 0 +max = 32000 + +[SDTC_VAR] +ifdef = ENABLE_NETWORK +var = network.max_password_time +type = SLE_UINT16 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_NETWORK_ONLY +def = 2000 +min = 0 +max = 32000 + [SDTC_BOOL] ifdef = ENABLE_NETWORK var = network.pause_on_join |