summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2010-10-17 17:40:18 +0000
committerrubidium <rubidium@openttd.org>2010-10-17 17:40:18 +0000
commitd9602f4ef936b79c1d1ee785477323618e46f9cf (patch)
tree1420d0f86e4559de83ab250a109d2c7f7bca5f53
parent459514afe4f550a08d98958745d6cd8311c53fdd (diff)
downloadopenttd-d9602f4ef936b79c1d1ee785477323618e46f9cf.tar.xz
(svn r20973) -Add: chat sending and receiving support for remote admins (dihedral)
-rw-r--r--src/network/core/tcp_admin.cpp4
-rw-r--r--src/network/core/tcp_admin.h22
-rw-r--r--src/network/network_admin.cpp58
-rw-r--r--src/network/network_admin.h6
-rw-r--r--src/network/network_func.h2
-rw-r--r--src/network/network_server.cpp14
-rw-r--r--src/settings_type.h1
-rw-r--r--src/table/settings.h1
8 files changed, 106 insertions, 2 deletions
diff --git a/src/network/core/tcp_admin.cpp b/src/network/core/tcp_admin.cpp
index 0d2d09fdd..b2da7475f 100644
--- a/src/network/core/tcp_admin.cpp
+++ b/src/network/core/tcp_admin.cpp
@@ -54,6 +54,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p)
ADMIN_COMMAND(ADMIN_PACKET_ADMIN_QUIT)
ADMIN_COMMAND(ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY)
ADMIN_COMMAND(ADMIN_PACKET_ADMIN_POLL)
+ ADMIN_COMMAND(ADMIN_PACKET_ADMIN_CHAT)
ADMIN_COMMAND(ADMIN_PACKET_SERVER_FULL)
ADMIN_COMMAND(ADMIN_PACKET_SERVER_BANNED)
@@ -75,6 +76,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p)
ADMIN_COMMAND(ADMIN_PACKET_SERVER_COMPANY_REMOVE)
ADMIN_COMMAND(ADMIN_PACKET_SERVER_COMPANY_ECONOMY)
ADMIN_COMMAND(ADMIN_PACKET_SERVER_COMPANY_STATS)
+ ADMIN_COMMAND(ADMIN_PACKET_SERVER_CHAT)
default:
if (this->HasClientQuit()) {
@@ -124,6 +126,7 @@ DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_JOIN)
DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_QUIT)
DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY)
DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_POLL)
+DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_CHAT)
DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_FULL)
DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_BANNED)
@@ -145,5 +148,6 @@ DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_COMPANY_UPDATE)
DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_COMPANY_REMOVE)
DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_COMPANY_ECONOMY)
DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_COMPANY_STATS)
+DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_CHAT)
#endif /* ENABLE_NETWORK */
diff --git a/src/network/core/tcp_admin.h b/src/network/core/tcp_admin.h
index 15f3ba0a7..e73d0202e 100644
--- a/src/network/core/tcp_admin.h
+++ b/src/network/core/tcp_admin.h
@@ -30,6 +30,7 @@ enum PacketAdminType {
ADMIN_PACKET_ADMIN_QUIT, ///< The admin tells the server that it is quitting.
ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY, ///< The admin tells the server the update frequency of a particular piece of information.
ADMIN_PACKET_ADMIN_POLL, ///< The admin explicitly polls for a piece of information.
+ ADMIN_PACKET_ADMIN_CHAT, ///< The admin sends a chat message to be distributed.
ADMIN_PACKET_SERVER_FULL = 100, ///< The server tells the admin it cannot accept the admin.
ADMIN_PACKET_SERVER_BANNED, ///< The server tells the admin it is banned.
@@ -51,6 +52,7 @@ enum PacketAdminType {
ADMIN_PACKET_SERVER_COMPANY_REMOVE, ///< The server tells the admin that a company was removed.
ADMIN_PACKET_SERVER_COMPANY_ECONOMY, ///< The server gives the admin some economy related company information.
ADMIN_PACKET_SERVER_COMPANY_STATS, ///< The server gives the admin some statistics about a company.
+ ADMIN_PACKET_SERVER_CHAT, ///< The server received a chat message and relays it.
INVALID_ADMIN_PACKET = 0xFF, ///< An invalid marker for admin packets.
};
@@ -69,6 +71,7 @@ enum AdminUpdateType {
ADMIN_UPDATE_COMPANY_INFO, ///< Updates about the generic information of companies.
ADMIN_UPDATE_COMPANY_ECONOMY, ///< Updates about the economy of companies.
ADMIN_UPDATE_COMPANY_STATS, ///< Updates about the statistics of companies.
+ ADMIN_UPDATE_CHAT, ///< The admin would like to have chat messages.
ADMIN_UPDATE_END ///< Must ALWAYS be on the end of this list!! (period)
};
@@ -131,6 +134,15 @@ protected:
DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_POLL);
/**
+ * Send chat as the server:
+ * uint8 Action such as NETWORK_ACTION_CHAT_CLIENT (see #NetworkAction).
+ * uint8 Destination type such as DESTTYPE_BROADCAST (see #DestType).
+ * uint32 ID of the destination such as company or client id.
+ * string Message.
+ */
+ DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_CHAT);
+
+ /**
* The server is full (connection gets closed).
*/
DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_FULL);
@@ -294,6 +306,16 @@ protected:
*/
DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_COMPANY_STATS);
+ /**
+ * Send chat from the game into the admin network:
+ * uint8 Action such as NETWORK_ACTION_CHAT_CLIENT (see #NetworkAction).
+ * uint8 Destination type such as DESTTYPE_BROADCAST (see #DestType).
+ * uint32 ID of the client who sent this message.
+ * string Message.
+ * uint64 Money (only when it is a 'give money' action).
+ */
+ DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_CHAT);
+
NetworkRecvStatus HandlePacket(Packet *p);
public:
NetworkRecvStatus CloseConnection(bool error = true);
diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp
index 7a86a4892..565976c70 100644
--- a/src/network/network_admin.cpp
+++ b/src/network/network_admin.cpp
@@ -45,6 +45,7 @@ static const AdminUpdateFrequency _admin_update_type_frequencies[] = {
ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_COMPANY_INFO
ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_COMPANY_ECONOMY
ADMIN_FREQUENCY_POLL | ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_COMPANY_STATS
+ ADMIN_FREQUENCY_AUTOMATIC, ///< ADMIN_UPDATE_CHAT
};
assert_compile(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END);
@@ -384,6 +385,20 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyStats()
return NETWORK_RECV_STATUS_OKAY;
}
+NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data)
+{
+ Packet *p = new Packet(ADMIN_PACKET_SERVER_CHAT);
+
+ p->Send_uint8 (action);
+ p->Send_uint8 (desttype);
+ p->Send_uint32(client_id);
+ p->Send_string(msg);
+ p->Send_uint64(data);
+
+ this->Send_Packet(p);
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
/***********
* Receiving functions
************/
@@ -496,6 +511,33 @@ DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_POLL)
return NETWORK_RECV_STATUS_OKAY;
}
+DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_CHAT)
+{
+ if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
+
+ NetworkAction action = (NetworkAction)p->Recv_uint8();
+ DestType desttype = (DestType)p->Recv_uint8();
+ int dest = p->Recv_uint32();
+
+ char msg[NETWORK_CHAT_LENGTH];
+ p->Recv_string(msg, NETWORK_CHAT_LENGTH);
+
+ switch (action) {
+ case NETWORK_ACTION_CHAT:
+ case NETWORK_ACTION_CHAT_CLIENT:
+ case NETWORK_ACTION_CHAT_COMPANY:
+ case NETWORK_ACTION_SERVER_MESSAGE:
+ NetworkServerSendChat(action, desttype, dest, msg, _network_own_client_id, 0, true);
+ break;
+
+ default:
+ DEBUG(net, 3, "[admin] Invalid chat action %d from admin '%s' (%s).", action, this->admin_name, this->admin_version);
+ return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
+ }
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
/*
* Useful wrapper functions
*/
@@ -613,6 +655,22 @@ void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bc
}
}
+
+/**
+ * Send chat to the admin network (if they did opt in for the respective update).
+ */
+void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data, bool from_admin)
+{
+ if (from_admin) return;
+
+ ServerNetworkAdminSocketHandler *as;
+ FOR_ALL_ADMIN_SOCKETS(as) {
+ if (as->update_frequency[ADMIN_UPDATE_CHAT] & ADMIN_FREQUENCY_AUTOMATIC) {
+ as->SendChat(action, desttype, client_id, msg, data);
+ }
+ }
+}
+
/**
* Send a Welcome packet to all connected admins
*/
diff --git a/src/network/network_admin.h b/src/network/network_admin.h
index 7f4f67de1..7174a191a 100644
--- a/src/network/network_admin.h
+++ b/src/network/network_admin.h
@@ -29,6 +29,7 @@ protected:
DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_QUIT);
DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY);
DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_POLL);
+ DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_CHAT);
NetworkRecvStatus SendProtocol();
public:
@@ -43,6 +44,7 @@ public:
NetworkRecvStatus SendWelcome();
NetworkRecvStatus SendNewGame();
NetworkRecvStatus SendShutdown();
+
NetworkRecvStatus SendDate();
NetworkRecvStatus SendClientJoin(ClientID client_id);
NetworkRecvStatus SendClientInfo(const NetworkClientInfo *ci);
@@ -56,6 +58,8 @@ public:
NetworkRecvStatus SendCompanyEconomy();
NetworkRecvStatus SendCompanyStats();
+ NetworkRecvStatus SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data);
+
static void Send();
static void AcceptConnection(SOCKET s, const NetworkAddress &address);
static bool AllowConnection();
@@ -81,6 +85,8 @@ void NetworkAdminClientError(ClientID client_id, NetworkErrorCode error_code);
void NetworkAdminCompanyInfo(const Company *company, bool new_company);
void NetworkAdminCompanyUpdate(const Company *company);
void NetworkAdminCompanyRemove(CompanyID company_id, AdminCompanyRemoveReason bcrr);
+
+void NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data = 0, bool from_admin = false);
void NetworkAdminUpdate(AdminUpdateFrequency freq);
#endif /* ENABLE_NETWORK */
diff --git a/src/network/network_func.h b/src/network/network_func.h
index 00db245e3..d6fc752d8 100644
--- a/src/network/network_func.h
+++ b/src/network/network_func.h
@@ -73,7 +73,7 @@ const char *GetClientIP(NetworkClientInfo *ci);
void NetworkServerDoMove(ClientID client_id, CompanyID company_id);
void NetworkServerSendRcon(ClientID client_id, ConsoleColour colour_code, const char *string);
-void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, ClientID from_id, int64 data = 0);
+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(const char *ip, bool ban);
diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp
index c49c9ed88..16b626ce5 100644
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -1159,7 +1159,7 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_ACK)
-void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data)
+void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, ClientID from_id, int64 data, bool from_admin)
{
NetworkClientSocket *cs;
const NetworkClientInfo *ci, *ci_own, *ci_to;
@@ -1172,6 +1172,10 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
/* Display the text locally, and that is it */
if (ci != NULL) {
NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
+
+ if (_settings_client.network.server_admin_chat) {
+ NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
+ }
}
} else {
/* Else find the client to send the message to */
@@ -1215,6 +1219,11 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
}
}
+ /* if the server can read it, let the admin network read it, too. */
+ if (_local_company == (CompanyID)dest && _settings_client.network.server_admin_chat) {
+ NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
+ }
+
ci = NetworkFindClientInfoFromClientID(from_id);
ci_own = NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER);
if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
@@ -1251,6 +1260,9 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
FOR_ALL_CLIENT_SOCKETS(cs) {
cs->SendChat(action, from_id, false, msg, data);
}
+
+ NetworkAdminChat(action, desttype, from_id, msg, data, from_admin);
+
ci = NetworkFindClientInfoFromClientID(from_id);
if (ci != NULL) {
NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
diff --git a/src/settings_type.h b/src/settings_type.h
index c6544043d..8e1b1bc9e 100644
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -134,6 +134,7 @@ struct NetworkSettings {
bool pause_on_join; ///< pause the game when people join
uint16 server_port; ///< port the server listens on
uint16 server_admin_port; ///< port the server listens on for the admin network
+ bool server_admin_chat; ///< allow private chat for the server to be distributed to the admin network
char server_name[NETWORK_NAME_LENGTH]; ///< name of the server
char server_password[NETWORK_PASSWORD_LENGTH]; ///< password for joining this server
char rcon_password[NETWORK_PASSWORD_LENGTH]; ///< password for rconsole (server side)
diff --git a/src/table/settings.h b/src/table/settings.h
index 0d263a85e..e01bc6823 100644
--- a/src/table/settings.h
+++ b/src/table/settings.h
@@ -632,6 +632,7 @@ const SettingDesc _settings[] = {
SDTC_BOOL(network.pause_on_join, S, NO, true, STR_NULL, NULL),
SDTC_VAR(network.server_port, SLE_UINT16, S, NO,NETWORK_DEFAULT_PORT,0,65535,0,STR_NULL, NULL),
SDTC_VAR(network.server_admin_port, SLE_UINT16, S, NO, NETWORK_ADMIN_PORT,0,65535,0,STR_NULL, NULL),
+ SDTC_BOOL(network.server_admin_chat, S, NO, true, STR_NULL, NULL),
SDTC_BOOL(network.server_advertise, S, NO, false, STR_NULL, NULL),
SDTC_VAR(network.lan_internet, SLE_UINT8, S, NO, 0, 0, 1, 0, STR_NULL, NULL),
SDTC_STR(network.client_name, SLE_STRB, S, 0, NULL, STR_NULL, UpdateClientName),