Update to 1.10.2

This commit is contained in:
Pavel Stupnikov
2020-06-02 01:52:45 +03:00
parent c7c3966eec
commit 0e8ed94e00
828 changed files with 146109 additions and 141846 deletions

View File

@@ -115,6 +115,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::ReceivePackets()
Packet *p;
while ((p = this->ReceivePacket()) != nullptr) {
NetworkRecvStatus res = this->HandlePacket(p);
delete p;
if (res != NETWORK_RECV_STATUS_OKAY) return res;
}

View File

@@ -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;
}

View File

@@ -83,15 +83,18 @@ public:
return "admin";
}
struct ServerNetworkAdminSocketHandlerFilter {
bool operator() (size_t index) { return ServerNetworkAdminSocketHandler::Get(index)->GetAdminStatus() == ADMIN_STATUS_ACTIVE; }
};
/**
* Returns an iterable ensemble of all active admin sockets
* @param from index of the first socket to consider
* @return an iterable ensemble of all active admin sockets
*/
static Pool::IterateWrapper<ServerNetworkAdminSocketHandler> IterateActive(size_t from = 0)
static Pool::IterateWrapperFiltered<ServerNetworkAdminSocketHandler, ServerNetworkAdminSocketHandlerFilter> IterateActive(size_t from = 0)
{
return Pool::IterateWrapper<ServerNetworkAdminSocketHandler>(from,
[](size_t index) { return ServerNetworkAdminSocketHandler::Get(index)->GetAdminStatus() == ADMIN_STATUS_ACTIVE; });
return Pool::IterateWrapperFiltered<ServerNetworkAdminSocketHandler, ServerNetworkAdminSocketHandlerFilter>(from, ServerNetworkAdminSocketHandlerFilter{});
}
};

View File

@@ -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();

View File

@@ -951,7 +951,7 @@ public:
{
if (this->auto_select && !rci->IsSelected()) _network_content_client.ToggleSelectedState(rci);
this->content.ForceRebuild();
this->InvalidateData();
this->InvalidateData(0, false);
}
void OnDownloadComplete(ContentID cid) override

View File

@@ -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);

View File

@@ -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)

View File

@@ -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) {
@@ -1589,7 +1595,20 @@ static void NetworkCheckRestartMap()
if (_settings_client.network.restart_game_year != 0 && _cur_year >= _settings_client.network.restart_game_year) {
DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
StartNewGameWithoutGUI(GENERATE_NEW_SEED);
_settings_newgame.game_creation.generation_seed = GENERATE_NEW_SEED;
switch(_file_to_saveload.abstract_ftype) {
case FT_SAVEGAME:
case FT_SCENARIO:
_switch_mode = SM_LOAD_GAME;
break;
case FT_HEIGHTMAP:
_switch_mode = SM_START_HEIGHTMAP;
break;
default:
_switch_mode = SM_NEWGAME;
}
}
}
@@ -2026,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) {
@@ -2064,11 +2086,16 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban)
uint n = 0;
/* There can be multiple clients with the same IP, kick them all */
/* There can be multiple clients with the same IP, kick them all but don't kill the server,
* or the client doing the rcon. The latter can't be kicked because kicking frees closes
* and subsequently free the connection related instances, which we would be reading from
* and writing to after returning. So we would read or write data from freed memory up till
* the segfault triggers. */
for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
if (cs->client_id == CLIENT_ID_SERVER) continue;
if (cs->client_id == _redirect_console_to_client) continue;
if (cs->client_address.IsInNetmask(ip)) {
NetworkServerKickClient(cs->client_id);
NetworkServerKickClient(cs->client_id, reason);
n++;
}
}

View File

@@ -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();

View File

@@ -74,14 +74,20 @@ enum NetworkPasswordType {
NETWORK_COMPANY_PASSWORD, ///< The password of the company.
};
/** Destination of our chat messages. */
/**
* Destination of our chat messages.
* @warning The values of the enum items are part of the admin network API. Only append at the end.
*/
enum DestType {
DESTTYPE_BROADCAST, ///< Send message/notice to all clients (All)
DESTTYPE_TEAM, ///< Send message/notice to everyone playing the same company (Team)
DESTTYPE_CLIENT, ///< Send message/notice to only a certain client (Private)
};
/** Actions that can be used for NetworkTextMessage */
/**
* Actions that can be used for NetworkTextMessage.
* @warning The values of the enum items are part of the admin network API. Only append at the end.
*/
enum NetworkAction {
NETWORK_ACTION_JOIN,
NETWORK_ACTION_LEAVE,
@@ -94,9 +100,13 @@ enum NetworkAction {
NETWORK_ACTION_COMPANY_SPECTATOR,
NETWORK_ACTION_COMPANY_JOIN,
NETWORK_ACTION_COMPANY_NEW,
NETWORK_ACTION_KICKED,
};
/** The error codes we send around in the protocols. */
/**
* The error codes we send around in the protocols.
* @warning The values of the enum items are part of the admin network API. Only append at the end.
*/
enum NetworkErrorCode {
NETWORK_ERROR_GENERAL, // Try to use this one like never