Mercurial > hg > openttd
changeset 15871:792676d7443d draft
(svn r20553) -Feature: allow rate limiting of incoming commands
author | rubidium <rubidium@openttd.org> |
---|---|
date | Thu, 19 Aug 2010 08:59:36 +0000 |
parents | c9d9786c445d |
children | 42574c590ecd |
files | src/lang/english.txt src/network/core/tcp_game.h src/network/network.cpp src/network/network_client.cpp src/network/network_command.cpp src/network/network_server.cpp src/network/network_type.h src/settings_type.h src/table/settings.h |
diffstat | 9 files changed, 31 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1757,6 +1757,7 @@ STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}You are banned from this server 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 ############ Leave those lines in this order!! STR_NETWORK_ERROR_CLIENT_GENERAL :general error @@ -1774,6 +1775,7 @@ STR_NETWORK_ERROR_CLIENT_KICKED :kicked by server STR_NETWORK_ERROR_CLIENT_CHEATER :was trying to use a cheat STR_NETWORK_ERROR_CLIENT_SERVER_FULL :server full +STR_NETWORK_ERROR_CLIENT_TOO_MANY_COMMANDS :was sending too many commands ############ End of leave-in-this-order # Network related errors
--- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -78,6 +78,7 @@ class CommandQueue { CommandPacket *first; ///< The first packet in the queue. CommandPacket *last; ///< The last packet in the queue; only valid when first != NULL. + uint count; ///< The number of items in the queue. public: /** Initialise the command queue. */ @@ -88,6 +89,8 @@ CommandPacket *Pop(); CommandPacket *Peek(); void Free(); + /** Get the number of items in the queue. */ + uint Count() const { return this->count; } }; /** Status of a client */
--- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -344,7 +344,8 @@ STR_NETWORK_ERROR_CLIENT_COMPANY_MISMATCH, STR_NETWORK_ERROR_CLIENT_KICKED, STR_NETWORK_ERROR_CLIENT_CHEATER, - STR_NETWORK_ERROR_CLIENT_SERVER_FULL + STR_NETWORK_ERROR_CLIENT_SERVER_FULL, + STR_NETWORK_ERROR_CLIENT_TOO_MANY_COMMANDS }; if (err >= (ptrdiff_t)lengthof(network_error_strings)) err = NETWORK_ERROR_GENERAL; @@ -1181,14 +1182,13 @@ f = NULL; } #endif /* DEBUG_DUMP_COMMANDS */ - NetworkDistributeCommands(); - if (_frame_counter >= _frame_counter_max) { /* Only check for active clients just before we're going to send out * the commands so we don't send multiple pause/unpause commands when - * the frame_freq is more than 1 tick. */ + * the frame_freq is more than 1 tick. Same with distributing commands. */ CheckPauseOnJoin(); CheckMinActiveClients(); + NetworkDistributeCommands(); } bool send_frame = false;
--- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -515,6 +515,9 @@ case NETWORK_ERROR_CHEATER: _switch_mode_errorstr = STR_NETWORK_ERROR_CHEATER; break; + case NETWORK_ERROR_TOO_MANY_COMMANDS: + _switch_mode_errorstr = STR_NETWORK_ERROR_TOO_MANY_COMMANDS; + break; default: _switch_mode_errorstr = STR_NETWORK_ERROR_LOSTCONNECTION; }
--- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -17,6 +17,7 @@ #include "network.h" #include "../command_func.h" #include "../company_func.h" +#include "../settings_type.h" /** Table with all the callbacks we'll use for conversion*/ static CommandCallback * const _callback_table[] = { @@ -68,6 +69,7 @@ this->last->next = add; } this->last = add; + this->count++; } /** @@ -77,7 +79,10 @@ CommandPacket *CommandQueue::Pop() { CommandPacket *ret = this->first; - if (ret != NULL) this->first = this->first->next; + if (ret != NULL) { + this->first = this->first->next; + this->count--; + } return ret; } @@ -97,6 +102,7 @@ while ((cp = this->Pop()) != NULL) { free(cp); } + assert(this->count == 0); } /** Local queue of packets waiting for handling. */ @@ -241,8 +247,10 @@ */ static void DistributeQueue(CommandQueue *queue, const NetworkClientSocket *owner) { + int to_go = _settings_client.network.commands_per_frame; + CommandPacket *cp; - while ((cp = queue->Pop()) != NULL) { + while (--to_go >= 0 && (cp = queue->Pop()) != NULL) { DistributeCommandPacket(*cp, owner); free(cp); }
--- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -897,6 +897,10 @@ return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); } + if (cs->incoming_queue.Count() >= _settings_client.network.max_commands_in_queue) { + return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_TOO_MANY_COMMANDS); + } + CommandPacket cp; const char *err = cs->Recv_Command(p, &cp);
--- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -110,6 +110,7 @@ NETWORK_ERROR_KICKED, NETWORK_ERROR_CHEATER, NETWORK_ERROR_FULL, + NETWORK_ERROR_TOO_MANY_COMMANDS, }; #endif /* ENABLE_NETWORK */
--- a/src/settings_type.h +++ b/src/settings_type.h @@ -128,6 +128,8 @@ #ifdef ENABLE_NETWORK uint16 sync_freq; ///< how often do we check whether we are still in-sync uint8 frame_freq; ///< how often do we send commands to the clients + uint16 commands_per_frame; ///< how many commands may be sent each frame_freq frames? + uint16 max_commands_in_queue; ///< how many commands may there be in the incoming queue before dropping the connection? uint16 max_join_time; ///< maximum amount of time, in game ticks, a client may take to join bool pause_on_join; ///< pause the game when people join uint16 server_port; ///< port the server listens on
--- a/src/table/settings.h +++ b/src/table/settings.h @@ -622,6 +622,8 @@ SDTC_VAR(network.sync_freq, SLE_UINT16,C|S,NO, 100, 0, 100, 0, STR_NULL, NULL), SDTC_VAR(network.frame_freq, SLE_UINT8,C|S,NO, 0, 0, 100, 0, STR_NULL, NULL), + SDTC_VAR(network.commands_per_frame, SLE_UINT16, S, NO, 4, 1, 65535, 0, STR_NULL, NULL), + SDTC_VAR(network.max_commands_in_queue,SLE_UINT16, S, NO, 32, 1, 65535, 0, STR_NULL, NULL), SDTC_VAR(network.max_join_time, SLE_UINT16, S, NO, 500, 0, 32000, 0, STR_NULL, NULL), SDTC_BOOL(network.pause_on_join, S, NO, true, STR_NULL, NULL), SDTC_VAR(network.server_port, SLE_UINT16, S, NO,NETWORK_DEFAULT_PORT,0,65535,0,STR_NULL, NULL),