summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2010-08-19 08:59:36 +0000
committerrubidium <rubidium@openttd.org>2010-08-19 08:59:36 +0000
commita4c6d07edc4937087e3f2d0b2bff52cc3980b9e2 (patch)
tree9a939be9e5c3b7bc5a0101cb3077a3d619d2dad8 /src
parentcfc0df152b40c7109ce6c2e60f80304fc97adb89 (diff)
downloadopenttd-a4c6d07edc4937087e3f2d0b2bff52cc3980b9e2.tar.xz
(svn r20553) -Feature: allow rate limiting of incoming commands
Diffstat (limited to 'src')
-rw-r--r--src/lang/english.txt2
-rw-r--r--src/network/core/tcp_game.h3
-rw-r--r--src/network/network.cpp8
-rw-r--r--src/network/network_client.cpp3
-rw-r--r--src/network/network_command.cpp12
-rw-r--r--src/network/network_server.cpp4
-rw-r--r--src/network/network_type.h1
-rw-r--r--src/settings_type.h2
-rw-r--r--src/table/settings.h2
9 files changed, 31 insertions, 6 deletions
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 4269adfd3..b4622708a 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1757,6 +1757,7 @@ STR_NETWORK_ERROR_SERVER_FULL :{WHITE}The serv
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_COMPANY_MISMATCH :wrong company i
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
diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h
index a7d3bb462..acbd47ed8 100644
--- a/src/network/core/tcp_game.h
+++ b/src/network/core/tcp_game.h
@@ -78,6 +78,7 @@ struct CommandPacket;
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 @@ public:
CommandPacket *Pop();
CommandPacket *Peek();
void Free();
+ /** Get the number of items in the queue. */
+ uint Count() const { return this->count; }
};
/** Status of a client */
diff --git a/src/network/network.cpp b/src/network/network.cpp
index cf74c621b..00863f8ad 100644
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -344,7 +344,8 @@ StringID GetNetworkErrorMsg(NetworkErrorCode err)
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 @@ void NetworkGameLoop()
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;
diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp
index ea478276b..b6ffcbb22 100644
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -515,6 +515,9 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR)
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;
}
diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp
index 1bec93c7a..1b1712203 100644
--- 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 @@ void CommandQueue::Append(CommandPacket *p)
this->last->next = add;
}
this->last = add;
+ this->count++;
}
/**
@@ -77,7 +79,10 @@ void CommandQueue::Append(CommandPacket *p)
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 @@ void CommandQueue::Free()
while ((cp = this->Pop()) != NULL) {
free(cp);
}
+ assert(this->count == 0);
}
/** Local queue of packets waiting for handling. */
@@ -241,8 +247,10 @@ static void DistributeCommandPacket(CommandPacket cp, const NetworkClientSocket
*/
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);
}
diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp
index dc7d9d0f6..b8ea9fa62 100644
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -897,6 +897,10 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
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);
diff --git a/src/network/network_type.h b/src/network/network_type.h
index a86ad9948..5b83620e6 100644
--- a/src/network/network_type.h
+++ b/src/network/network_type.h
@@ -110,6 +110,7 @@ enum NetworkErrorCode {
NETWORK_ERROR_KICKED,
NETWORK_ERROR_CHEATER,
NETWORK_ERROR_FULL,
+ NETWORK_ERROR_TOO_MANY_COMMANDS,
};
#endif /* ENABLE_NETWORK */
diff --git a/src/settings_type.h b/src/settings_type.h
index f5a9a85d4..ba546895c 100644
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -128,6 +128,8 @@ struct NetworkSettings {
#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
diff --git a/src/table/settings.h b/src/table/settings.h
index 86ef0c23b..2c75eefc7 100644
--- a/src/table/settings.h
+++ b/src/table/settings.h
@@ -622,6 +622,8 @@ const SettingDesc _settings[] = {
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),