summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2011-04-09 21:52:38 +0000
committerrubidium <rubidium@openttd.org>2011-04-09 21:52:38 +0000
commitd1a50a01b46684486428a2b63959cb160a016c39 (patch)
tree860b03560d9a7e540e4c633d0bb0118350abf401
parent6ce83c0aaa4028f05088c9c613f6b7b08b250aab (diff)
downloadopenttd-d1a50a01b46684486428a2b63959cb160a016c39.tar.xz
(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
-rw-r--r--src/network/network_client.cpp9
-rw-r--r--src/network/network_server.cpp57
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;