1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-20 13:09:15 +00:00

(svn r23764) -Fix [FS#4955]: make default timeouts for certain states lower and configurable

This commit is contained in:
rubidium
2012-01-06 21:49:06 +00:00
parent 9d958ff581
commit bddfcaef95
6 changed files with 116 additions and 45 deletions

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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 */