From b594990071fd6cff1c530c2fb4139c9aaaba6e08 Mon Sep 17 00:00:00 2001 From: rubidium Date: Wed, 18 Aug 2010 22:40:17 +0000 Subject: (svn r20549) -Codechange: centralise the handling of the incoming commands (from clients and the server) --- src/network/network_command.cpp | 99 ++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 32 deletions(-) (limited to 'src/network/network_command.cpp') 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(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,23 +99,11 @@ 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(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) @@ -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); } @@ -225,6 +208,58 @@ void NetworkFreeLocalCommandQueue() _local_execution_queue.Free(); } +/** + * "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. -- cgit v1.2.3-54-g00ecf