Feature #7756: Allow server to supply a reason to kicked/banned clients
This commit adds the missing feature of allowing the server owner to
provide a reason for kicking/banning a client, which the client sees in
a pop-up window after being kicked. The implementation extends the
network protocol by adding a new network action called
NETWORK_ACTION_KICKED that is capable of having an error string, unlike
the other network error packages. Additionally, the kick function
broadcasts a message to all clients about the kicked client and the
reason for the kick.
This commit is contained in:
committed by
Charles Pigott
parent
b5d56559d2
commit
5880f1479f
@@ -248,6 +248,7 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send,
|
||||
case NETWORK_ACTION_GIVE_MONEY: strid = self_send ? STR_NETWORK_MESSAGE_GAVE_MONEY_AWAY : STR_NETWORK_MESSAGE_GIVE_MONEY; break;
|
||||
case NETWORK_ACTION_CHAT_COMPANY: strid = self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY; break;
|
||||
case NETWORK_ACTION_CHAT_CLIENT: strid = self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT; break;
|
||||
case NETWORK_ACTION_KICKED: strid = STR_NETWORK_MESSAGE_KICKED; break;
|
||||
default: strid = STR_NETWORK_CHAT_ALL; break;
|
||||
}
|
||||
|
||||
|
||||
@@ -687,8 +687,15 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p
|
||||
|
||||
StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
|
||||
if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
|
||||
|
||||
ShowErrorMessage(err, INVALID_STRING_ID, WL_CRITICAL);
|
||||
/* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */
|
||||
if (error == NETWORK_ERROR_KICKED && p->CanReadFromPacket(1)) {
|
||||
char kick_msg[255];
|
||||
p->Recv_string(kick_msg, sizeof(kick_msg));
|
||||
SetDParamStr(0, kick_msg);
|
||||
ShowErrorMessage(err, STR_NETWORK_ERROR_KICK_MESSAGE, WL_CRITICAL);
|
||||
} else {
|
||||
ShowErrorMessage(err, INVALID_STRING_ID, WL_CRITICAL);
|
||||
}
|
||||
|
||||
/* Perform an emergency save if we had already entered the game */
|
||||
if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave();
|
||||
|
||||
@@ -75,9 +75,9 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id);
|
||||
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string);
|
||||
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, ClientID from_id, int64 data = 0, bool from_admin = false);
|
||||
|
||||
void NetworkServerKickClient(ClientID client_id);
|
||||
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban);
|
||||
uint NetworkServerKickOrBanIP(const char *ip, bool ban);
|
||||
void NetworkServerKickClient(ClientID client_id, const char *reason);
|
||||
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason);
|
||||
uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason);
|
||||
|
||||
void NetworkInitChatMessage();
|
||||
void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message, ...) WARN_FORMAT(3, 4);
|
||||
|
||||
@@ -1687,12 +1687,12 @@ static WindowDesc _client_list_popup_desc(
|
||||
/* Here we start to define the options out of the menu */
|
||||
static void ClientList_Kick(const NetworkClientInfo *ci)
|
||||
{
|
||||
NetworkServerKickClient(ci->client_id);
|
||||
NetworkServerKickClient(ci->client_id, nullptr);
|
||||
}
|
||||
|
||||
static void ClientList_Ban(const NetworkClientInfo *ci)
|
||||
{
|
||||
NetworkServerKickOrBanIP(ci->client_id, true);
|
||||
NetworkServerKickOrBanIP(ci->client_id, true, nullptr);
|
||||
}
|
||||
|
||||
static void ClientList_GiveMoney(const NetworkClientInfo *ci)
|
||||
|
||||
@@ -407,13 +407,15 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo()
|
||||
/**
|
||||
* Send an error to the client, and close its connection.
|
||||
* @param error The error to disconnect for.
|
||||
* @param reason In case of kicking a client, specifies the reason for kicking the client.
|
||||
*/
|
||||
NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode error)
|
||||
NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode error, const char *reason)
|
||||
{
|
||||
char str[100];
|
||||
Packet *p = new Packet(PACKET_SERVER_ERROR);
|
||||
|
||||
p->Send_uint8(error);
|
||||
if (reason != nullptr) p->Send_string(reason);
|
||||
this->SendPacket(p);
|
||||
|
||||
StringID strid = GetNetworkErrorMsg(error);
|
||||
@@ -427,7 +429,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err
|
||||
|
||||
DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
|
||||
|
||||
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
|
||||
if (error == NETWORK_ERROR_KICKED && reason != nullptr) {
|
||||
NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid);
|
||||
} else {
|
||||
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
|
||||
}
|
||||
|
||||
for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
|
||||
if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
|
||||
@@ -2039,29 +2045,32 @@ void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const cha
|
||||
/**
|
||||
* Kick a single client.
|
||||
* @param client_id The client to kick.
|
||||
* @param reason In case of kicking a client, specifies the reason for kicking the client.
|
||||
*/
|
||||
void NetworkServerKickClient(ClientID client_id)
|
||||
void NetworkServerKickClient(ClientID client_id, const char *reason)
|
||||
{
|
||||
if (client_id == CLIENT_ID_SERVER) return;
|
||||
NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED);
|
||||
NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ban, or kick, everyone joined from the given client's IP.
|
||||
* @param client_id The client to check for.
|
||||
* @param ban Whether to ban or kick.
|
||||
* @param reason In case of kicking a client, specifies the reason for kicking the client.
|
||||
*/
|
||||
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban)
|
||||
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason)
|
||||
{
|
||||
return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban);
|
||||
return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick or ban someone based on an IP address.
|
||||
* @param ip The IP address/range to ban/kick.
|
||||
* @param ban Whether to ban or just kick.
|
||||
* @param reason In case of kicking a client, specifies the reason for kicking the client.
|
||||
*/
|
||||
uint NetworkServerKickOrBanIP(const char *ip, bool ban)
|
||||
uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason)
|
||||
{
|
||||
/* Add address to ban-list */
|
||||
if (ban) {
|
||||
@@ -2081,7 +2090,7 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban)
|
||||
for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
|
||||
if (cs->client_id == CLIENT_ID_SERVER) continue;
|
||||
if (cs->client_address.IsInNetmask(ip)) {
|
||||
NetworkServerKickClient(cs->client_id);
|
||||
NetworkServerKickClient(cs->client_id, reason);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
NetworkRecvStatus SendMove(ClientID client_id, CompanyID company_id);
|
||||
|
||||
NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci);
|
||||
NetworkRecvStatus SendError(NetworkErrorCode error);
|
||||
NetworkRecvStatus SendError(NetworkErrorCode error, const char *reason = nullptr);
|
||||
NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data);
|
||||
NetworkRecvStatus SendJoin(ClientID client_id);
|
||||
NetworkRecvStatus SendFrame();
|
||||
|
||||
@@ -85,6 +85,7 @@ enum DestType {
|
||||
enum NetworkAction {
|
||||
NETWORK_ACTION_JOIN,
|
||||
NETWORK_ACTION_LEAVE,
|
||||
NETWORK_ACTION_KICKED,
|
||||
NETWORK_ACTION_SERVER_MESSAGE,
|
||||
NETWORK_ACTION_CHAT,
|
||||
NETWORK_ACTION_CHAT_COMPANY,
|
||||
|
||||
Reference in New Issue
Block a user