From d1a50a01b46684486428a2b63959cb160a016c39 Mon Sep 17 00:00:00 2001 From: rubidium Date: Sat, 9 Apr 2011 21:52:38 +0000 Subject: (svn r22308) -Fix [FS#4574]: waiting on a server could kick the client, or rather the client would kick itself due to an unexpected packet --- src/network/network_client.cpp | 9 +++---- src/network/network_server.cpp | 57 +++++++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 1bd288a2e..66eff8fdb 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -719,17 +719,14 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_WELCOME) DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_WAIT) { - if (this->status != STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - this->status = STATUS_MAP_WAIT; + /* We set the internal wait state when requesting the map. */ + if (this->status != STATUS_MAP_WAIT) return NETWORK_RECV_STATUS_MALFORMED_PACKET; + /* But... only now we set the join status to waiting, instead of requesting. */ _network_join_status = NETWORK_JOIN_STATUS_WAITING; _network_join_waiting = p->Recv_uint8(); SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0); - /* We are put on hold for receiving the map.. we need GUI for this ;) */ - DEBUG(net, 1, "The server is currently busy sending the map to someone else, please wait..." ); - DEBUG(net, 1, "There are %d clients in front of you", _network_join_waiting); - return NETWORK_RECV_STATUS_OKAY; } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 0d5fb1c6f..55dff4f50 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -539,9 +539,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() if (this->status == STATUS_MAP) { if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical(); + bool last_packet = false; + for (uint i = 0; i < sent_packets && this->savegame_packets != NULL; i++) { Packet *p = this->savegame_packets; - bool last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE; + last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE; /* Remove the packet from the savegame queue and put it in the real queue. */ this->savegame_packets = p->next; @@ -549,31 +551,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() this->NetworkTCPSocketHandler::SendPacket(p); if (last_packet) { - /* Done reading! */ - - /* Set the status to DONE_MAP, no we will wait for the client - * to send it is ready (maybe that happens like never ;)) */ - this->status = STATUS_DONE_MAP; - - NetworkClientSocket *new_cs; - bool new_map_client = false; - /* Check if there is a client waiting for receiving the map - * and start sending him the map */ - FOR_ALL_CLIENT_SOCKETS(new_cs) { - if (new_cs->status == STATUS_MAP_WAIT) { - /* Check if we already have a new client to send the map to */ - if (!new_map_client) { - /* If not, this client will get the map */ - new_cs->status = STATUS_AUTHORIZED; - new_map_client = true; - new_cs->SendMap(); - } else { - /* Else, send the other clients how many clients are in front of them */ - new_cs->SendWait(); - } - } - } - /* There is no more data, so break the for */ break; } @@ -581,6 +558,34 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical(); + if (last_packet) { + /* Done reading, make sure saving is done as well */ + WaitTillSaved(); + + /* Set the status to DONE_MAP, no we will wait for the client + * to send it is ready (maybe that happens like never ;)) */ + this->status = STATUS_DONE_MAP; + + NetworkClientSocket *new_cs; + bool new_map_client = false; + /* Check if there is a client waiting for receiving the map + * and start sending him the map */ + FOR_ALL_CLIENT_SOCKETS(new_cs) { + if (new_cs->status == STATUS_MAP_WAIT) { + /* Check if we already have a new client to send the map to */ + if (!new_map_client) { + /* If not, this client will get the map */ + new_cs->status = STATUS_AUTHORIZED; + new_map_client = true; + new_cs->SendMap(); + } else { + /* Else, send the other clients how many clients are in front of them */ + new_cs->SendWait(); + } + } + } + } + switch (this->SendPackets()) { case SPS_CLOSED: return NETWORK_RECV_STATUS_CONN_LOST; -- cgit v1.2.3-54-g00ecf