| 233 | } |
| 234 | |
| 235 | NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status) |
| 236 | { |
| 237 | assert(status != NETWORK_RECV_STATUS_OKAY); |
| 238 | /* |
| 239 | * Sending a message just before leaving the game calls cs->SendPackets. |
| 240 | * This might invoke this function, which means that when we close the |
| 241 | * connection after cs->SendPackets we will close an already closed |
| 242 | * connection. This handles that case gracefully without having to make |
| 243 | * that code any more complex or more aware of the validity of the socket. |
| 244 | */ |
| 245 | if (this->IsPendingDeletion() || this->sock == INVALID_SOCKET) return status; |
| 246 | |
| 247 | if (status != NETWORK_RECV_STATUS_CLIENT_QUIT && status != NETWORK_RECV_STATUS_SERVER_ERROR && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) { |
| 248 | /* We did not receive a leave message from this client... */ |
| 249 | std::string client_name = this->GetClientName(); |
| 250 | |
| 251 | NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "", STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST); |
| 252 | |
| 253 | /* Inform other clients of this... strange leaving ;) */ |
| 254 | for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) { |
| 255 | if (new_cs->status >= STATUS_AUTHORIZED && this != new_cs) { |
| 256 | new_cs->SendErrorQuit(this->client_id, NETWORK_ERROR_CONNECTION_LOST); |
| 257 | } |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | /* If we were transferring a map to this client, stop the savegame creation |
| 262 | * process and queue the next client to receive the map. */ |
| 263 | if (this->status == STATUS_MAP) { |
| 264 | /* Ensure the saving of the game is stopped too. */ |
| 265 | this->savegame->Destroy(); |
| 266 | this->savegame = nullptr; |
| 267 | |
| 268 | this->CheckNextClientToSendMap(this); |
| 269 | } |
| 270 | |
| 271 | NetworkAdminClientError(this->client_id, NETWORK_ERROR_CONNECTION_LOST); |
| 272 | Debug(net, 3, "[{}] Client #{} closed connection", ServerNetworkGameSocketHandler::GetName(), this->client_id); |
| 273 | |
| 274 | /* We just lost one client :( */ |
| 275 | if (this->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--; |
| 276 | extern uint8_t _network_clients_connected; |
| 277 | _network_clients_connected--; |
| 278 | |
| 279 | this->SendPackets(true); |
| 280 | |
| 281 | this->DeferDeletion(); |
| 282 | |
| 283 | return status; |
| 284 | } |
| 285 | |
| 286 | /** |
| 287 | * Whether an connection is allowed or not at this moment. |
no test coverage detected