1
0
Fork 0

Codechange: [Network] Use std::string to determine an unique name for clients

pull/9312/head
rubidium42 2021-05-29 20:22:41 +02:00 committed by rubidium42
parent 806f78aa04
commit e3c9ed4d15
3 changed files with 24 additions and 30 deletions

View File

@ -1358,9 +1358,8 @@ void NetworkUpdateClientName(const std::string &client_name)
MyClient::SendSetName(client_name); MyClient::SendSetName(client_name);
} else { } else {
/* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */ /* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */
char temporary_name[NETWORK_CLIENT_NAME_LENGTH]; std::string temporary_name = client_name;
strecpy(temporary_name, client_name.c_str(), lastof(temporary_name)); if (NetworkMakeClientNameUnique(temporary_name)) {
if (NetworkFindName(temporary_name, lastof(temporary_name))) {
NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name); NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name);
ci->client_name = temporary_name; ci->client_name = temporary_name;
NetworkUpdateClientInfo(CLIENT_ID_SERVER); NetworkUpdateClientInfo(CLIENT_ID_SERVER);

View File

@ -117,7 +117,7 @@ void ShowNetworkError(StringID error_string);
void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str = "", int64 data = 0); void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str = "", int64 data = 0);
uint NetworkCalculateLag(const NetworkClientSocket *cs); uint NetworkCalculateLag(const NetworkClientSocket *cs);
StringID GetNetworkErrorMsg(NetworkErrorCode err); StringID GetNetworkErrorMsg(NetworkErrorCode err);
bool NetworkFindName(char *new_name, const char *last); bool NetworkMakeClientNameUnique(std::string &new_name);
std::string GenerateCompanyPasswordHash(const std::string &password, const std::string &password_server_id, uint32 password_game_seed); std::string GenerateCompanyPasswordHash(const std::string &password, const std::string &password_server_id, uint32 password_game_seed);
NetworkAddress ParseConnectionString(const std::string &connection_string, uint16 default_port); NetworkAddress ParseConnectionString(const std::string &connection_string, uint16 default_port);

View File

@ -874,8 +874,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
return this->SendError(NETWORK_ERROR_NOT_EXPECTED); return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
} }
char name[NETWORK_CLIENT_NAME_LENGTH];
CompanyID playas;
char client_revision[NETWORK_REVISION_LENGTH]; char client_revision[NETWORK_REVISION_LENGTH];
p->Recv_string(client_revision, sizeof(client_revision)); p->Recv_string(client_revision, sizeof(client_revision));
@ -887,8 +885,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
return this->SendError(NETWORK_ERROR_WRONG_REVISION); return this->SendError(NETWORK_ERROR_WRONG_REVISION);
} }
p->Recv_string(name, sizeof(name)); std::string client_name = p->Recv_string(NETWORK_CLIENT_NAME_LENGTH);
playas = (Owner)p->Recv_uint8(); CompanyID playas = (Owner)p->Recv_uint8();
if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT;
@ -911,14 +909,14 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
break; break;
} }
if (!NetworkIsValidClientName(name)) { if (!NetworkIsValidClientName(client_name)) {
/* An invalid client name was given. However, the client ensures the name /* An invalid client name was given. However, the client ensures the name
* is valid before it is sent over the network, so something went horribly * is valid before it is sent over the network, so something went horribly
* wrong. This is probably someone trying to troll us. */ * wrong. This is probably someone trying to troll us. */
return this->SendError(NETWORK_ERROR_INVALID_CLIENT_NAME); return this->SendError(NETWORK_ERROR_INVALID_CLIENT_NAME);
} }
if (!NetworkFindName(name, lastof(name))) { // Change name if duplicate if (!NetworkMakeClientNameUnique(client_name)) { // Change name if duplicate
/* We could not create a name for this client */ /* We could not create a name for this client */
return this->SendError(NETWORK_ERROR_NAME_IN_USE); return this->SendError(NETWORK_ERROR_NAME_IN_USE);
} }
@ -927,7 +925,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
NetworkClientInfo *ci = new NetworkClientInfo(this->client_id); NetworkClientInfo *ci = new NetworkClientInfo(this->client_id);
this->SetInfo(ci); this->SetInfo(ci);
ci->join_date = _date; ci->join_date = _date;
ci->client_name = name; ci->client_name = client_name;
ci->client_playas = playas; ci->client_playas = playas;
DEBUG(desync, 1, "client: %08x; %02x; %02x; %02x", _date, _date_fract, (int)ci->client_playas, (int)ci->index); DEBUG(desync, 1, "client: %08x; %02x; %02x; %02x", _date, _date_fract, (int)ci->client_playas, (int)ci->index);
@ -1394,10 +1392,9 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet
return this->SendError(NETWORK_ERROR_NOT_EXPECTED); return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
} }
char client_name[NETWORK_CLIENT_NAME_LENGTH];
NetworkClientInfo *ci; NetworkClientInfo *ci;
p->Recv_string(client_name, sizeof(client_name)); std::string client_name = p->Recv_string(NETWORK_CLIENT_NAME_LENGTH);
ci = this->GetInfo(); ci = this->GetInfo();
if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT; if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CLIENT_QUIT;
@ -1411,7 +1408,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet
} }
/* Display change */ /* Display change */
if (NetworkFindName(client_name, lastof(client_name))) { if (NetworkMakeClientNameUnique(client_name)) {
NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name); NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, client_name);
ci->client_name = client_name; ci->client_name = client_name;
NetworkUpdateClientInfo(ci->client_id); NetworkUpdateClientInfo(ci->client_id);
@ -1673,42 +1670,40 @@ static void NetworkAutoCleanCompanies()
/** /**
* Check whether a name is unique, and otherwise try to make it unique. * Check whether a name is unique, and otherwise try to make it unique.
* @param new_name The name to check/modify. * @param new_name The name to check/modify.
* @param last The last writeable element of the buffer.
* @return True if an unique name was achieved. * @return True if an unique name was achieved.
*/ */
bool NetworkFindName(char *new_name, const char *last) bool NetworkMakeClientNameUnique(std::string &name)
{ {
bool found_name = false; bool is_name_unique = false;
uint number = 0; uint number = 0;
char original_name[NETWORK_CLIENT_NAME_LENGTH]; std::string original_name = name;
strecpy(original_name, new_name, lastof(original_name)); while (!is_name_unique) {
is_name_unique = true;
while (!found_name) {
found_name = true;
for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
if (ci->client_name.compare(new_name) == 0) { if (ci->client_name.compare(name) == 0) {
/* Name already in use */ /* Name already in use */
found_name = false; is_name_unique = false;
break; break;
} }
} }
/* Check if it is the same as the server-name */ /* Check if it is the same as the server-name */
const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER); const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
if (ci != nullptr) { if (ci != nullptr) {
if (ci->client_name.compare(new_name) == 0) found_name = false; // name already in use if (ci->client_name.compare(name) == 0) is_name_unique = false; // name already in use
} }
if (!found_name) { if (!is_name_unique) {
/* Try a new name (<name> #1, <name> #2, and so on) */ /* Try a new name (<name> #1, <name> #2, and so on) */
name = original_name + " #" + std::to_string(number);
/* Something's really wrong when there're more names than clients */ /* The constructed client name is larger than the limit,
if (number++ > MAX_CLIENTS) break; * so... bail out as no valid name can be created. */
seprintf(new_name, last, "%s #%d", original_name, number); if (name.size() >= NETWORK_CLIENT_NAME_LENGTH) return false;
} }
} }
return found_name; return is_name_unique;
} }
/** /**