diff options
Diffstat (limited to 'src/network/network_server.cpp')
-rw-r--r-- | src/network/network_server.cpp | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 6c65aaced..de36ef9da 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -67,13 +67,22 @@ struct PacketWriter : SaveFilter { */ PacketWriter(ServerNetworkGameSocketHandler *cs) : SaveFilter(NULL), cs(cs), current(NULL), total_size(0) { + this->cs->savegame_mutex = ThreadMutex::New(); } /** Make sure everything is cleaned up. */ ~PacketWriter() { + /* Prevent double frees. */ - this->cs->savegame = NULL; + if (this->cs != NULL) { + if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical(); + this->cs->savegame = NULL; + if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical(); + + delete this->cs->savegame_mutex; + this->cs->savegame_mutex = NULL; + } delete this->current; } @@ -94,10 +103,12 @@ struct PacketWriter : SaveFilter { /* virtual */ void Write(byte *buf, size_t size) { - if (cs == NULL) return; + if (this->cs == NULL) return; if (this->current == NULL) this->current = new Packet(PACKET_SERVER_MAP_DATA); + if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical(); + byte *bufe = buf + size; while (buf != bufe) { size_t to_write = min(SEND_MTU - this->current->size, bufe - buf); @@ -111,11 +122,17 @@ struct PacketWriter : SaveFilter { } } + if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical(); + this->total_size += size; } /* virtual */ void Finish() { + if (this->cs == NULL) return; + + if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical(); + /* Make sure the last packet is flushed. */ this->AppendQueue(); @@ -126,7 +143,9 @@ struct PacketWriter : SaveFilter { /* Fast-track the size to the client. */ Packet *p = new Packet(PACKET_SERVER_MAP_SIZE); p->Send_uint32(this->total_size); - this->cs->SendPacket(p); + this->cs->NetworkTCPSocketHandler::SendPacket(p); + + if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical(); } }; @@ -153,7 +172,13 @@ ServerNetworkGameSocketHandler::~ServerNetworkGameSocketHandler() { if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID; OrderBackup::ResetUser(this->client_id); + + if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical(); delete this->savegame_packets; + if (this->savegame != NULL) this->savegame->cs = NULL; + + if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical(); + delete this->savegame_mutex; } Packet *ServerNetworkGameSocketHandler::ReceivePacket() @@ -169,6 +194,13 @@ Packet *ServerNetworkGameSocketHandler::ReceivePacket() return p; } +void ServerNetworkGameSocketHandler::SendPacket(Packet *packet) +{ + if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical(); + this->NetworkTCPSocketHandler::SendPacket(packet); + if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical(); +} + NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status) { assert(status != NETWORK_RECV_STATUS_OKAY); @@ -479,10 +511,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() sent_packets = 4; // We start with trying 4 packets /* Make a dump of the current game */ - if (SaveWithFilter(this->savegame, false) != SL_OK) usererror("network savedump failed"); + if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed"); } if (this->status == STATUS_MAP) { + if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical(); + 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; @@ -490,7 +524,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() /* Remove the packet from the savegame queue and put it in the real queue. */ this->savegame_packets = p->next; p->next = NULL; - this->SendPacket(p); + this->NetworkTCPSocketHandler::SendPacket(p); if (last_packet) { /* Done reading! */ @@ -531,6 +565,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() /* Not everything is sent, decrease the sent_packets */ if (sent_packets > 1) sent_packets /= 2; } + + if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical(); } return NETWORK_RECV_STATUS_OKAY; } |