summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/network/core/tcp_game.h1
-rw-r--r--src/network/network.cpp2
-rw-r--r--src/network/network_client.cpp5
-rw-r--r--src/network/network_command.cpp99
-rw-r--r--src/network/network_internal.h2
-rw-r--r--src/network/network_server.cpp25
6 files changed, 73 insertions, 61 deletions
diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h
index f150a5f08..a7d3bb462 100644
--- a/src/network/core/tcp_game.h
+++ b/src/network/core/tcp_game.h
@@ -122,6 +122,7 @@ public:
ClientStatus status; ///< Status of this client
+ CommandQueue incoming_queue; ///< The command-queue awaiting handling
CommandQueue outgoing_queue; ///< The command-queue awaiting delivery
NetworkRecvStatus CloseConnection(bool error = true);
diff --git a/src/network/network.cpp b/src/network/network.cpp
index e868bbd2f..cf74c621b 100644
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -1181,6 +1181,8 @@ 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
diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp
index a764a0410..ea478276b 100644
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -742,16 +742,13 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND)
const char *err = MY_CLIENT->Recv_Command(p, &cp);
cp.frame = p->Recv_uint32();
cp.my_cmd = p->Recv_bool();
- cp.next = NULL;
if (err != NULL) {
IConsolePrintF(CC_ERROR, "WARNING: %s from server, dropping...", err);
return NETWORK_RECV_STATUS_MALFORMED_PACKET;
}
- /* The server did send us this command..
- * queue it in our own queue, so we can handle it in the upcoming frame! */
- NetworkAddCommandQueue(cp);
+ MY_CLIENT->incoming_queue.Append(&cp);
return NETWORK_RECV_STATUS_OKAY;
}
diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp
index 6f6cae886..1bec93c7a 100644
--- a/src/network/network_command.cpp
+++ b/src/network/network_command.cpp
@@ -55,16 +55,19 @@ static CommandCallback * const _callback_table[] = {
/**
* Append a CommandPacket at the end of the queue.
* @param p The packet to append to the queue.
+ * @note A new instance of the CommandPacket will be made.
*/
void CommandQueue::Append(CommandPacket *p)
{
- assert(p != NULL);
+ CommandPacket *add = MallocT<CommandPacket>(1);
+ *add = *p;
+ add->next = NULL;
if (this->first == NULL) {
- this->first = p;
+ this->first = add;
} else {
- this->last->next = p;
+ this->last->next = add;
}
- this->last = p;
+ this->last = add;
}
/**
@@ -96,24 +99,12 @@ void CommandQueue::Free()
}
}
-
+/** Local queue of packets waiting for handling. */
+static CommandQueue _local_wait_queue;
/** Local queue of packets waiting for execution. */
static CommandQueue _local_execution_queue;
/**
- * Add a command to the local or client socket command queue,
- * based on the socket.
- * @param cp the command packet to add
- * @param cs the socket to send to (NULL = locally)
- */
-void NetworkAddCommandQueue(CommandPacket cp, NetworkClientSocket *cs)
-{
- CommandPacket *new_cp = MallocT<CommandPacket>(1);
- *new_cp = cp;
- (cs == NULL ? _local_execution_queue : cs->outgoing_queue).Append(new_cp);
-}
-
-/**
* Prepare a DoCommand to be send over the network
* @param tile The tile to perform a command on (see #CommandProc)
* @param p1 Additional data for the command (see #CommandProc)
@@ -129,7 +120,6 @@ void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comma
CommandPacket c;
c.company = company;
- c.next = NULL;
c.tile = tile;
c.p1 = p1;
c.p2 = p2;
@@ -148,15 +138,7 @@ void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comma
c.frame = _frame_counter_max + 1;
c.my_cmd = true;
- NetworkAddCommandQueue(c);
-
- /* Only the local client (in this case, the server) gets the callback */
- c.callback = 0;
- /* And we queue it for delivery to the clients */
- NetworkClientSocket *cs;
- FOR_ALL_CLIENT_SOCKETS(cs) {
- if (cs->status > STATUS_MAP_WAIT) NetworkAddCommandQueue(c, cs);
- }
+ _local_wait_queue.Append(&c);
return;
}
@@ -180,8 +162,7 @@ void NetworkSyncCommandQueue(NetworkClientSocket *cs)
for (CommandPacket *p = _local_execution_queue.Peek(); p != NULL; p = p->next) {
CommandPacket c = *p;
c.callback = 0;
- c.next = NULL;
- NetworkAddCommandQueue(c, cs);
+ cs->outgoing_queue.Append(&c);
}
}
@@ -192,8 +173,10 @@ void NetworkExecuteLocalCommandQueue()
{
assert(IsLocalCompany());
+ CommandQueue &queue = (_network_server ? _local_execution_queue : NetworkClientSocket::Get(0)->incoming_queue);
+
CommandPacket *cp;
- while ((cp = _local_execution_queue.Peek()) != NULL) {
+ while ((cp = queue.Peek()) != NULL) {
/* The queue is always in order, which means
* that the first element will be executed first. */
if (_frame_counter < cp->frame) break;
@@ -209,7 +192,7 @@ void NetworkExecuteLocalCommandQueue()
cp->cmd |= CMD_NETWORK_COMMAND;
DoCommandP(cp, cp->my_cmd);
- _local_execution_queue.Pop();
+ queue.Pop();
free(cp);
}
@@ -226,6 +209,58 @@ void NetworkFreeLocalCommandQueue()
}
/**
+ * "Send" a particular CommandPacket to all clients.
+ * @param cp The command that has to be distributed.
+ * @param owner The client that owns the command,
+ */
+static void DistributeCommandPacket(CommandPacket cp, const NetworkClientSocket *owner)
+{
+ CommandCallback *callback = cp.callback;
+ cp.frame = _frame_counter_max + 1;
+
+ NetworkClientSocket *cs;
+ FOR_ALL_CLIENT_SOCKETS(cs) {
+ if (cs->status >= STATUS_MAP) {
+ /* Callbacks are only send back to the client who sent them in the
+ * first place. This filters that out. */
+ cp.callback = (cs != owner) ? NULL : callback;
+ cp.my_cmd = (cs == owner);
+ cs->outgoing_queue.Append(&cp);
+ }
+ }
+
+ cp.callback = (cs != owner) ? NULL : callback;
+ cp.my_cmd = (cs == owner);
+ _local_execution_queue.Append(&cp);
+}
+
+/**
+ * "Send" a particular CommandQueue to all clients.
+ * @param queue The queue of commands that has to be distributed.
+ * @param owner The client that owns the commands,
+ */
+static void DistributeQueue(CommandQueue *queue, const NetworkClientSocket *owner)
+{
+ CommandPacket *cp;
+ while ((cp = queue->Pop()) != NULL) {
+ DistributeCommandPacket(*cp, owner);
+ free(cp);
+ }
+}
+
+void NetworkDistributeCommands()
+{
+ /* First send the server's commands. */
+ DistributeQueue(&_local_wait_queue, NULL);
+
+ /* Then send the queues of the others. */
+ NetworkClientSocket *cs;
+ FOR_ALL_CLIENT_SOCKETS(cs) {
+ DistributeQueue(&cs->incoming_queue, cs);
+ }
+}
+
+/**
* Receives a command from the network.
* @param p the packet to read from.
* @param cp the struct to write the data to.
diff --git a/src/network/network_internal.h b/src/network/network_internal.h
index 3131cc10e..7cb30e23d 100644
--- a/src/network/network_internal.h
+++ b/src/network/network_internal.h
@@ -160,7 +160,7 @@ struct CommandPacket : CommandContainer {
bool my_cmd; ///< did the command originate from "me"
};
-void NetworkAddCommandQueue(CommandPacket cp, NetworkClientSocket *cs = NULL);
+void NetworkDistributeCommands();
void NetworkExecuteLocalCommandQueue();
void NetworkFreeLocalCommandQueue();
void NetworkSyncCommandQueue(NetworkClientSocket *cs);
diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp
index e9cb791d5..dc7d9d0f6 100644
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -891,8 +891,6 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
*/
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
{
- NetworkClientSocket *new_cs;
-
/* The client was never joined.. so this is impossible, right?
* Ignore the packet, give the client a warning, and close his connection */
if (cs->status < STATUS_DONE_MAP || cs->HasClientQuit()) {
@@ -947,28 +945,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = cs->client_id;
- /* The frame can be executed in the same frame as the next frame-packet
- * That frame just before that frame is saved in _frame_counter_max */
- cp.frame = _frame_counter_max + 1;
- cp.next = NULL;
-
- CommandCallback *callback = cp.callback;
-
- /* Queue the command for the clients (are send at the end of the frame
- * if they can handle it ;)) */
- FOR_ALL_CLIENT_SOCKETS(new_cs) {
- if (new_cs->status >= STATUS_MAP) {
- /* Callbacks are only send back to the client who sent them in the
- * first place. This filters that out. */
- cp.callback = (new_cs != cs) ? NULL : callback;
- cp.my_cmd = (new_cs == cs);
- NetworkAddCommandQueue(cp, new_cs);
- }
- }
-
- cp.callback = NULL;
- cp.my_cmd = false;
- NetworkAddCommandQueue(cp);
+ cs->incoming_queue.Append(&cp);
return NETWORK_RECV_STATUS_OKAY;
}