Changeset - r25431:ee9e6d792f6e
[Not reviewed]
master
0 6 0
Patric Stout - 3 years ago 2021-05-11 10:26:16
truebrain@openttd.org
Fix: [Network] clients leaving because of broken connections was not broadcasted (#9238)

The code mixed up "client has quit but we already told everyone"
with "client lost connection, handle this".

Split up those two signals:
- CLIENT_QUIT means we told everyone and the connection is now dead
- CONNECTION_LIST means we should tell everyone we lost a client
6 files changed with 25 insertions and 24 deletions:
0 comments (0 inline, 0 general)
src/network/core/core.h
Show inline comments
 
@@ -20,16 +20,17 @@ void NetworkCoreShutdown();
 

	
 
/** Status of a network client; reasons why a client has quit */
 
enum NetworkRecvStatus {
 
	NETWORK_RECV_STATUS_OKAY,             ///< Everything is okay
 
	NETWORK_RECV_STATUS_DESYNC,           ///< A desync did occur
 
	NETWORK_RECV_STATUS_NEWGRF_MISMATCH,  ///< We did not have the required NewGRFs
 
	NETWORK_RECV_STATUS_SAVEGAME,         ///< Something went wrong (down)loading the savegame
 
	NETWORK_RECV_STATUS_CONN_LOST,        ///< The connection is 'just' lost
 
	NETWORK_RECV_STATUS_MALFORMED_PACKET, ///< We apparently send a malformed packet
 
	NETWORK_RECV_STATUS_SERVER_ERROR,     ///< The server told us we made an error
 
	NETWORK_RECV_STATUS_SERVER_FULL,      ///< The server is full
 
	NETWORK_RECV_STATUS_SERVER_BANNED,    ///< The server has banned us
 
	NETWORK_RECV_STATUS_CLOSE_QUERY,      ///< Done querying the server
 
	NETWORK_RECV_STATUS_OKAY,             ///< Everything is okay.
 
	NETWORK_RECV_STATUS_DESYNC,           ///< A desync did occur.
 
	NETWORK_RECV_STATUS_NEWGRF_MISMATCH,  ///< We did not have the required NewGRFs.
 
	NETWORK_RECV_STATUS_SAVEGAME,         ///< Something went wrong (down)loading the savegame.
 
	NETWORK_RECV_STATUS_CLIENT_QUIT,      ///< The connection is lost gracefully. Other clients are already informed of this leaving client.
 
	NETWORK_RECV_STATUS_MALFORMED_PACKET, ///< We apparently send a malformed packet.
 
	NETWORK_RECV_STATUS_SERVER_ERROR,     ///< The server told us we made an error.
 
	NETWORK_RECV_STATUS_SERVER_FULL,      ///< The server is full.
 
	NETWORK_RECV_STATUS_SERVER_BANNED,    ///< The server has banned us.
 
	NETWORK_RECV_STATUS_CLOSE_QUERY,      ///< Done querying the server.
 
	NETWORK_RECV_STATUS_CONNECTION_LOST,  ///< The connection is lost unexpectedly.
 
};
 

	
 
/** Forward declaration due to circular dependencies */
src/network/core/tcp_admin.cpp
Show inline comments
 
@@ -41,7 +41,7 @@ NetworkAdminSocketHandler::~NetworkAdmin
 
NetworkRecvStatus NetworkAdminSocketHandler::CloseConnection(bool error)
 
{
 
	delete this;
 
	return NETWORK_RECV_STATUS_CONN_LOST;
 
	return NETWORK_RECV_STATUS_CLIENT_QUIT;
 
}
 

	
 
/**
src/network/core/tcp_game.cpp
Show inline comments
 
@@ -48,10 +48,10 @@ NetworkRecvStatus NetworkGameSocketHandl
 
		_networking = false;
 
		ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL);
 

	
 
		return NETWORK_RECV_STATUS_CONN_LOST;
 
		return NETWORK_RECV_STATUS_CLIENT_QUIT;
 
	}
 

	
 
	return this->CloseConnection(error ? NETWORK_RECV_STATUS_SERVER_ERROR : NETWORK_RECV_STATUS_CONN_LOST);
 
	return this->CloseConnection(NETWORK_RECV_STATUS_CONNECTION_LOST);
 
}
 

	
 

	
src/network/network.cpp
Show inline comments
 
@@ -585,13 +585,13 @@ void NetworkClose(bool close_admins)
 
		}
 

	
 
		for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
 
			cs->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
 
			cs->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
 
		}
 
		ServerNetworkGameSocketHandler::CloseListeners();
 
		ServerNetworkAdminSocketHandler::CloseListeners();
 
	} else if (MyClient::my_client != nullptr) {
 
		MyClient::SendQuit();
 
		MyClient::my_client->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
 
		MyClient::my_client->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
 
	}
 

	
 
	TCPConnecter::KillAll();
src/network/network_client.cpp
Show inline comments
 
@@ -656,7 +656,7 @@ NetworkRecvStatus ClientNetworkGameSocke
 
	p->Recv_string(name, sizeof(name));
 

	
 
	if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 
	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT;
 
	/* The server validates the name when receiving it from clients, so when it is wrong
 
	 * here something went really wrong. In the best case the packet got malformed on its
 
	 * way too us, in the worst case the server is broken or compromised. */
src/network/network_server.cpp
Show inline comments
 
@@ -256,7 +256,7 @@ NetworkRecvStatus ServerNetworkGameSocke
 
	 */
 
	if (this->sock == INVALID_SOCKET) return status;
 

	
 
	if (status != NETWORK_RECV_STATUS_CONN_LOST && status != NETWORK_RECV_STATUS_SERVER_ERROR && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) {
 
	if (status != NETWORK_RECV_STATUS_CLIENT_QUIT && status != NETWORK_RECV_STATUS_SERVER_ERROR && !this->HasClientQuit() && this->status >= STATUS_AUTHORIZED) {
 
		/* We did not receive a leave message from this client... */
 
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 

	
 
@@ -893,7 +893,7 @@ NetworkRecvStatus ServerNetworkGameSocke
 
	p->Recv_string(name, sizeof(name));
 
	playas = (Owner)p->Recv_uint8();
 

	
 
	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT;
 

	
 
	/* join another company does not affect these values */
 
	switch (playas) {
 
@@ -1077,7 +1077,7 @@ NetworkRecvStatus ServerNetworkGameSocke
 
	CommandPacket cp;
 
	const char *err = this->ReceiveCommand(p, &cp);
 

	
 
	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT;
 

	
 
	NetworkClientInfo *ci = this->GetInfo();
 

	
 
@@ -1136,7 +1136,7 @@ NetworkRecvStatus ServerNetworkGameSocke
 

	
 
	/* The client was never joined.. thank the client for the packet, but ignore it */
 
	if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
 
		return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
 
		return this->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
 
	}
 

	
 
	this->GetClientName(client_name, lastof(client_name));
 
@@ -1156,7 +1156,7 @@ NetworkRecvStatus ServerNetworkGameSocke
 

	
 
	NetworkAdminClientError(this->client_id, errorno);
 

	
 
	return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
 
	return this->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
 
}
 

	
 
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet *p)
 
@@ -1167,7 +1167,7 @@ NetworkRecvStatus ServerNetworkGameSocke
 

	
 
	/* The client was never joined.. thank the client for the packet, but ignore it */
 
	if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
 
		return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
 
		return this->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
 
	}
 

	
 
	this->GetClientName(client_name, lastof(client_name));
 
@@ -1182,7 +1182,7 @@ NetworkRecvStatus ServerNetworkGameSocke
 

	
 
	NetworkAdminClientQuit(this->client_id);
 

	
 
	return this->CloseConnection(NETWORK_RECV_STATUS_CONN_LOST);
 
	return this->CloseConnection(NETWORK_RECV_STATUS_CLIENT_QUIT);
 
}
 

	
 
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ACK(Packet *p)
 
@@ -1412,7 +1412,7 @@ NetworkRecvStatus ServerNetworkGameSocke
 
	p->Recv_string(client_name, sizeof(client_name));
 
	ci = this->GetInfo();
 

	
 
	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT;
 

	
 
	if (ci != nullptr) {
 
		if (!NetworkIsValidClientName(client_name)) {
0 comments (0 inline, 0 general)