1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

address #2073, graceful KickPlayer with message, disconnect reason messages, chat player name and text different color

This commit is contained in:
zsilencer
2015-11-01 01:50:44 -06:00
parent d18adc80de
commit 34dff6f46b
2 changed files with 97 additions and 39 deletions

View File

@@ -51,10 +51,10 @@ extern "C" {
Network gNetwork;
enum {
NETWORK_SUCCESS,
NETWORK_NO_DATA,
NETWORK_MORE_DATA,
NETWORK_DISCONNECTED
NETWORK_READPACKET_SUCCESS,
NETWORK_READPACKET_NO_DATA,
NETWORK_READPACKET_MORE_DATA,
NETWORK_READPACKET_DISCONNECTED
};
enum {
@@ -66,6 +66,7 @@ enum {
NETWORK_COMMAND_PLAYERLIST,
NETWORK_COMMAND_PING,
NETWORK_COMMAND_PINGLIST,
NETWORK_COMMAND_SETDISCONNECTMSG,
NETWORK_COMMAND_MAX
};
@@ -159,6 +160,8 @@ NetworkConnection::NetworkConnection()
authstatus = NETWORK_AUTH_NONE;
player = 0;
socket = INVALID_SOCKET;
ResetLastPacketTime();
last_disconnect_reason = NULL;
}
NetworkConnection::~NetworkConnection()
@@ -175,16 +178,16 @@ int NetworkConnection::ReadPacket()
int readBytes = recv(socket, &((char*)&inboundpacket.size)[inboundpacket.transferred], sizeof(inboundpacket.size) - inboundpacket.transferred, 0);
if (readBytes == SOCKET_ERROR || readBytes == 0) {
if (LAST_SOCKET_ERROR() != EWOULDBLOCK && LAST_SOCKET_ERROR() != EAGAIN) {
return NETWORK_DISCONNECTED;
return NETWORK_READPACKET_DISCONNECTED;
} else {
return NETWORK_NO_DATA;
return NETWORK_READPACKET_NO_DATA;
}
}
inboundpacket.transferred += readBytes;
if (inboundpacket.transferred == sizeof(inboundpacket.size)) {
inboundpacket.size = ntohs(inboundpacket.size);
if(inboundpacket.size == 0){ // Can't have a size 0 packet
return NETWORK_DISCONNECTED;
return NETWORK_READPACKET_DISCONNECTED;
}
inboundpacket.data->resize(inboundpacket.size);
}
@@ -194,18 +197,19 @@ int NetworkConnection::ReadPacket()
int readBytes = recv(socket, (char*)&inboundpacket.GetData()[inboundpacket.transferred - sizeof(inboundpacket.size)], sizeof(inboundpacket.size) + inboundpacket.size - inboundpacket.transferred, 0);
if (readBytes == SOCKET_ERROR || readBytes == 0) {
if (LAST_SOCKET_ERROR() != EWOULDBLOCK && LAST_SOCKET_ERROR() != EAGAIN) {
return NETWORK_DISCONNECTED;
return NETWORK_READPACKET_DISCONNECTED;
} else {
return NETWORK_NO_DATA;
return NETWORK_READPACKET_NO_DATA;
}
}
inboundpacket.transferred += readBytes;
}
if (inboundpacket.transferred == sizeof(inboundpacket.size) + inboundpacket.size) {
return NETWORK_SUCCESS;
last_packet_time = SDL_GetTicks();
return NETWORK_READPACKET_SUCCESS;
}
}
return NETWORK_MORE_DATA;
return NETWORK_READPACKET_MORE_DATA;
}
bool NetworkConnection::SendPacket(NetworkPacket& packet)
@@ -264,6 +268,19 @@ bool NetworkConnection::SetNonBlocking(SOCKET socket, bool on)
#endif
}
void NetworkConnection::ResetLastPacketTime()
{
last_packet_time = SDL_GetTicks();
}
bool NetworkConnection::ReceivedPacketRecently()
{
if (SDL_TICKS_PASSED(SDL_GetTicks(), last_packet_time + 7000)) {
return false;
}
return true;
}
NetworkAddress::NetworkAddress()
{
ss = std::make_shared<sockaddr_storage>();
@@ -349,6 +366,7 @@ Network::Network()
client_command_handlers[NETWORK_COMMAND_PLAYERLIST] = &Network::Client_Handle_PLAYERLIST;
client_command_handlers[NETWORK_COMMAND_PING] = &Network::Client_Handle_PING;
client_command_handlers[NETWORK_COMMAND_PINGLIST] = &Network::Client_Handle_PINGLIST;
client_command_handlers[NETWORK_COMMAND_SETDISCONNECTMSG] = &Network::Client_Handle_SETDISCONNECTMSG;
server_command_handlers.resize(NETWORK_COMMAND_MAX, 0);
server_command_handlers[NETWORK_COMMAND_AUTH] = &Network::Server_Handle_AUTH;
server_command_handlers[NETWORK_COMMAND_CHAT] = &Network::Server_Handle_CHAT;
@@ -389,6 +407,7 @@ void Network::Close()
mode = NETWORK_MODE_NONE;
status = NETWORK_STATUS_NONE;
server_connection.authstatus = NETWORK_AUTH_NONE;
server_connection.last_disconnect_reason = NULL;
client_connection_list.clear();
game_command_queue.clear();
@@ -619,6 +638,7 @@ void Network::UpdateClient()
}
if (error == 0) {
status = NETWORK_STATUS_CONNECTED;
server_connection.ResetLastPacketTime();
Client_Send_AUTH(OPENRCT2_VERSION, gConfigNetwork.player_name, "");
window_network_status_open("Authenticating...");
}
@@ -626,7 +646,14 @@ void Network::UpdateClient()
}break;
case NETWORK_STATUS_CONNECTED:
if (!ProcessConnection(server_connection)) {
window_network_status_open("Connection closed");
char errormsg[256];
char reason[100];
reason[0] = 0;
if (server_connection.last_disconnect_reason) {
sprintf(reason, ": %s", server_connection.last_disconnect_reason);
}
sprintf(errormsg, "Disconnected%s", reason);
window_network_status_open(errormsg);
Close();
}
ProcessGameCommandQueue();
@@ -665,10 +692,13 @@ const char* Network::FormatChat(NetworkPlayer* fromplayer, const char* text)
if (fromplayer) {
lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE);
lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE);
safe_strncpy(lineCh, (const char*)fromplayer->name, 1024);
safe_strncpy(lineCh, (const char*)fromplayer->name, sizeof(fromplayer->name));
strcat(lineCh, ": ");
lineCh = strchr(lineCh, '\0');
}
strcat(formatted, text);
lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE);
lineCh = utf8_write_codepoint(lineCh, FORMAT_WHITE);
safe_strncpy(lineCh, text, 800);
return formatted;
}
@@ -806,37 +836,45 @@ void Network::Server_Send_PINGLIST()
SendPacketToClients(*packet);
}
void Network::Server_Send_SETDISCONNECTMSG(NetworkConnection& connection, const char* msg)
{
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_SETDISCONNECTMSG;
packet->WriteString(msg);
connection.QueuePacket(std::move(packet));
}
bool Network::ProcessConnection(NetworkConnection& connection)
{
connection.SendQueuedPackets();
int packetStatus;
do {
packetStatus = connection.ReadPacket();
switch(packetStatus) {
case NETWORK_DISCONNECTED:
case NETWORK_READPACKET_DISCONNECTED:
// closed connection or network error
PrintError();
if (GetMode() == NETWORK_MODE_CLIENT) {
printf("Server disconnected...\n");
return false;
} else
if (GetMode() == NETWORK_MODE_SERVER) {
printf("Client disconnected...\n");
return false;
if (!connection.last_disconnect_reason) {
connection.last_disconnect_reason = "Connection Closed";
}
return false;
break;
case NETWORK_SUCCESS:
case NETWORK_READPACKET_SUCCESS:
// done reading in packet
ProcessPacket(connection, connection.inboundpacket);
break;
case NETWORK_MORE_DATA:
case NETWORK_READPACKET_MORE_DATA:
// more data required to be read
break;
case NETWORK_NO_DATA:
case NETWORK_READPACKET_NO_DATA:
// could not read anything from socket
break;
}
} while (packetStatus == NETWORK_MORE_DATA || packetStatus == NETWORK_SUCCESS);
connection.SendQueuedPackets();
} while (packetStatus == NETWORK_READPACKET_MORE_DATA || packetStatus == NETWORK_READPACKET_SUCCESS);
if (!connection.ReceivedPacketRecently()) {
connection.last_disconnect_reason = "No Data";
return false;
}
return true;
}
@@ -893,7 +931,12 @@ void Network::RemoveClient(std::unique_ptr<NetworkConnection>& connection)
char* lineCh = text;
lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE);
lineCh = utf8_write_codepoint(lineCh, FORMAT_RED);
sprintf(lineCh, "%s has disconnected", connection_player->name);
char reasonstr[100];
reasonstr[0] = 0;
if (connection->last_disconnect_reason) {
sprintf(reasonstr, " (%s)", connection->last_disconnect_reason);
}
sprintf(lineCh, "%s has disconnected%s", connection_player->name, reasonstr);
chat_history_add(text);
gNetwork.Server_Send_CHAT(text);
}
@@ -1026,7 +1069,7 @@ int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pac
int Network::Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet)
{
const char* text = (char*)packet.Read(packet.size - packet.read);
const char* text = packet.ReadString();
if (text) {
chat_history_add(text);
}
@@ -1035,7 +1078,7 @@ int Network::Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& pa
int Network::Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet)
{
const char* text = (const char*)packet.Read(packet.size - packet.read);
const char* text = packet.ReadString();
if (text) {
const char* formatted = FormatChat(connection.player, text);
chat_history_add(formatted);
@@ -1135,6 +1178,17 @@ int Network::Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket
return 1;
}
int Network::Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet)
{
static char msg[256] = {0};
const char* disconnectmsg = packet.ReadString();
if (disconnectmsg) {
safe_strncpy(msg, disconnectmsg, sizeof(msg));
connection.last_disconnect_reason = msg;
}
return 1;
}
int network_init()
{
return gNetwork.Init();
@@ -1249,14 +1303,10 @@ void Network::KickPlayer(int playerId)
NetworkPlayer *player = GetPlayerByID(playerId);
for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
if ((*it)->player->id == playerId) {
char buffer[128];
sprintf(buffer, "%s has been kicked.", (*it)->player->name);
// Disconnect the client
closesocket((*it)->socket);
chat_history_add(buffer);
Server_Send_CHAT(buffer);
// Disconnect the client gracefully
(*it)->last_disconnect_reason = "Kicked";
Server_Send_SETDISCONNECTMSG(*(*it), "Get out of the server!");
shutdown((*it)->socket, SHUT_RD);
break;
}
}

View File

@@ -66,6 +66,9 @@ extern "C" {
#define LAST_SOCKET_ERROR() WSAGetLastError()
#undef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#ifndef SHUT_RD
#define SHUT_RD SD_RECEIVE
#endif
#else
#include <arpa/inet.h>
#include <netdb.h>
@@ -143,16 +146,20 @@ public:
bool SetTCPNoDelay(bool on);
bool SetNonBlocking(bool on);
static bool SetNonBlocking(SOCKET socket, bool on);
void ResetLastPacketTime();
bool ReceivedPacketRecently();
SOCKET socket;
NetworkPacket inboundpacket;
int authstatus;
NetworkPlayer* player;
uint32 ping_time;
const char* last_disconnect_reason;
private:
bool SendPacket(NetworkPacket& packet);
std::list<std::unique_ptr<NetworkPacket>> outboundpackets;
uint32 last_packet_time;
};
class NetworkAddress
@@ -214,6 +221,7 @@ public:
void Client_Send_PING();
void Server_Send_PING();
void Server_Send_PINGLIST();
void Server_Send_SETDISCONNECTMSG(NetworkConnection& connection, const char* msg);
std::vector<std::unique_ptr<NetworkPlayer>> player_list;
@@ -257,7 +265,6 @@ private:
bool _desynchronised;
uint32 server_connect_time;
void UpdateServer();
void UpdateClient();
@@ -276,6 +283,7 @@ private:
int Client_Handle_PING(NetworkConnection& connection, NetworkPacket& packet);
int Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet);
int Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet);
int Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet);
};
#endif // __cplusplus