Mercurial > hg > openttd
changeset 16223:87eaf077e2a1 draft
(svn r20924) -Codechange: make the game connection packet handling look more like UDP/content packet handling
author | rubidium <rubidium@openttd.org> |
---|---|
date | Fri, 15 Oct 2010 13:47:37 +0000 |
parents | 1a34081a4bc4 |
children | 8192961db36e |
files | src/network/core/tcp_content.cpp src/network/core/tcp_game.cpp src/network/core/tcp_game.h src/network/network.cpp src/network/network_client.cpp src/network/network_client.h src/network/network_server.cpp src/network/network_server.h |
diffstat | 8 files changed, 387 insertions(+), 303 deletions(-) [+] |
line wrap: on
line diff
--- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -115,7 +115,7 @@ } /** - * Receive a packet at UDP level + * Receive a packet at TCP level */ void NetworkContentSocketHandler::Recv_Packets() {
--- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -18,6 +18,7 @@ #include "../network.h" #include "../network_internal.h" #include "../../core/pool_func.hpp" +#include "../../debug.h" #include "table/strings.h" @@ -63,4 +64,147 @@ return NetworkCloseClient(this, error ? NETWORK_RECV_STATUS_SERVER_ERROR : NETWORK_RECV_STATUS_CONN_LOST); } + +/** + * Defines a simple (switch) case for each network packet + * @param type the packet type to create the case for + */ +#define GAME_COMMAND(type) case type: return this->NetworkPacketReceive_ ## type ## _command(p); break; + +/** + * Handle the given packet, i.e. pass it to the right parser receive command. + * @param p the packet to handle + * @return #NetworkRecvStatus of handling. + */ +NetworkRecvStatus NetworkClientSocket::HandlePacket(Packet *p) +{ + PacketGameType type = (PacketGameType)p->Recv_uint8(); + + switch (this->HasClientQuit() ? PACKET_END : type) { + GAME_COMMAND(PACKET_SERVER_FULL) + GAME_COMMAND(PACKET_SERVER_BANNED) + GAME_COMMAND(PACKET_CLIENT_JOIN) + GAME_COMMAND(PACKET_SERVER_ERROR) + GAME_COMMAND(PACKET_CLIENT_COMPANY_INFO) + GAME_COMMAND(PACKET_SERVER_COMPANY_INFO) + GAME_COMMAND(PACKET_SERVER_CLIENT_INFO) + GAME_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD) + GAME_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD) + GAME_COMMAND(PACKET_CLIENT_GAME_PASSWORD) + GAME_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD) + GAME_COMMAND(PACKET_SERVER_WELCOME) + GAME_COMMAND(PACKET_CLIENT_GETMAP) + GAME_COMMAND(PACKET_SERVER_WAIT) + GAME_COMMAND(PACKET_SERVER_MAP) + GAME_COMMAND(PACKET_CLIENT_MAP_OK) + GAME_COMMAND(PACKET_SERVER_JOIN) + GAME_COMMAND(PACKET_SERVER_FRAME) + GAME_COMMAND(PACKET_SERVER_SYNC) + GAME_COMMAND(PACKET_CLIENT_ACK) + GAME_COMMAND(PACKET_CLIENT_COMMAND) + GAME_COMMAND(PACKET_SERVER_COMMAND) + GAME_COMMAND(PACKET_CLIENT_CHAT) + GAME_COMMAND(PACKET_SERVER_CHAT) + GAME_COMMAND(PACKET_CLIENT_SET_PASSWORD) + GAME_COMMAND(PACKET_CLIENT_SET_NAME) + GAME_COMMAND(PACKET_CLIENT_QUIT) + GAME_COMMAND(PACKET_CLIENT_ERROR) + GAME_COMMAND(PACKET_SERVER_QUIT) + GAME_COMMAND(PACKET_SERVER_ERROR_QUIT) + GAME_COMMAND(PACKET_SERVER_SHUTDOWN) + GAME_COMMAND(PACKET_SERVER_NEWGAME) + GAME_COMMAND(PACKET_SERVER_RCON) + GAME_COMMAND(PACKET_CLIENT_RCON) + GAME_COMMAND(PACKET_SERVER_CHECK_NEWGRFS) + GAME_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED) + GAME_COMMAND(PACKET_SERVER_MOVE) + GAME_COMMAND(PACKET_CLIENT_MOVE) + GAME_COMMAND(PACKET_SERVER_COMPANY_UPDATE) + GAME_COMMAND(PACKET_SERVER_CONFIG_UPDATE) + + default: + this->CloseConnection(); + + if (this->HasClientQuit()) { + DEBUG(net, 0, "[tcp/game] received invalid packet type %d from client %d", type, this->client_id); + } else { + DEBUG(net, 0, "[tcp/game] received illegal packet from client %d", this->client_id); + } + return NETWORK_RECV_STATUS_MALFORMED_PACKET; + } +} + +/** + * Do the actual receiving of packets. + * As long as HandlePacket returns OKAY packets are handled. Upon + * failure, or no more packets to process the last result of + * HandlePacket is returned. + * @return #NetworkRecvStatus of the last handled packet. + */ +NetworkRecvStatus NetworkClientSocket::Recv_Packets() +{ + Packet *p; + while ((p = this->Recv_Packet()) != NULL) { + NetworkRecvStatus res = HandlePacket(p); + if (res != NETWORK_RECV_STATUS_OKAY) return res; + } + + return NETWORK_RECV_STATUS_OKAY; +} + +/** + * Create stub implementations for all receive commands that only + * show a warning that the given command is not available for the + * socket where the packet came from. + * @param type the packet type to create the stub for + */ +#define DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(type) \ +NetworkRecvStatus NetworkClientSocket::NetworkPacketReceive_## type ##_command(Packet *p) \ +{ \ + DEBUG(net, 0, "[tcp/game] received illegal packet type %d from client %d", \ + type, this->client_id); \ + return NETWORK_RECV_STATUS_MALFORMED_PACKET; \ +} + +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FULL) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_BANNED) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_JOIN) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WELCOME) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WAIT) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MAP) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_JOIN) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FRAME) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SYNC) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ACK) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMMAND) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_CHAT) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHAT) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_QUIT) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ERROR) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_QUIT) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_RCON) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_RCON) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MOVE) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MOVE) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE) +DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE) + #endif /* ENABLE_NETWORK */
--- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -27,7 +27,7 @@ * it protects old clients from joining newer servers * (because SERVER_ERROR is the respond to a wrong revision) */ -enum TCPPacketType { +enum PacketGameType { PACKET_SERVER_FULL, PACKET_SERVER_BANNED, PACKET_CLIENT_JOIN, @@ -113,12 +113,59 @@ typedef Pool<NetworkClientSocket, ClientIndex, 8, MAX_CLIENT_SLOTS> NetworkClientSocketPool; extern NetworkClientSocketPool _networkclientsocket_pool; +#define DECLARE_GAME_RECEIVE_COMMAND(type) virtual NetworkRecvStatus NetworkPacketReceive_## type ##_command(Packet *p) +#define DEF_GAME_RECEIVE_COMMAND(cls, type) NetworkRecvStatus cls ##NetworkGameSocketHandler::NetworkPacketReceive_ ## type ## _command(Packet *p) + /** Base socket handler for all TCP sockets */ class NetworkGameSocketHandler : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkTCPSocketHandler { /* TODO: rewrite into a proper class */ private: NetworkClientInfo *info; ///< Client info related to this socket + protected: + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FULL); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_BANNED); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_JOIN); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WELCOME); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WAIT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MAP); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_JOIN); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FRAME); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SYNC); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ACK); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMMAND); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_CHAT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHAT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_QUIT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ERROR); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_QUIT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_RCON); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_RCON); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MOVE); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MOVE); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE); + + NetworkRecvStatus HandlePacket(Packet *p); + NetworkGameSocketHandler(SOCKET s); public: ClientID client_id; ///< Client identifier @@ -137,6 +184,8 @@ inline void SetInfo(NetworkClientInfo *info) { assert(info != NULL && this->info == NULL); this->info = info; } inline NetworkClientInfo *GetInfo() const { return this->info; } + NetworkRecvStatus Recv_Packets(); + const char *Recv_Command(Packet *p, CommandPacket *cp); void Send_Command(Packet *p, const CommandPacket *cp); };
--- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -939,14 +939,14 @@ cs->writable = !!FD_ISSET(cs->sock, &write_fd); if (FD_ISSET(cs->sock, &read_fd)) { if (_network_server) { - NetworkServer_ReadPackets(cs); + cs->Recv_Packets(); } else { NetworkRecvStatus res; /* The client already was quiting! */ if (cs->HasClientQuit()) return false; - res = NetworkClient_ReadPackets(cs); + res = cs->Recv_Packets(); if (res != NETWORK_RECV_STATUS_OKAY) { /* The client made an error of which we can not recover * close the client and drop back to main menu */
--- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -392,7 +392,7 @@ extern bool SafeSaveOrLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir); extern StringID _switch_mode_errorstr; -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FULL) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_FULL) { /* We try to join a server which is full */ _switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_FULL; @@ -401,7 +401,7 @@ return NETWORK_RECV_STATUS_SERVER_FULL; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_BANNED) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_BANNED) { /* We try to join a server where we are banned */ _switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_BANNED; @@ -410,11 +410,11 @@ return NETWORK_RECV_STATUS_SERVER_BANNED; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_COMPANY_INFO) { byte company_info_version = p->Recv_uint8(); - if (!MY_CLIENT->HasClientQuit() && company_info_version == NETWORK_COMPANY_INFO_VERSION) { + if (!this->HasClientQuit() && company_info_version == NETWORK_COMPANY_INFO_VERSION) { /* We have received all data... (there are no more packets coming) */ if (!p->Recv_bool()) return NETWORK_RECV_STATUS_CLOSE_QUERY; @@ -452,7 +452,7 @@ /* This packet contains info about the client (playas and name) * as client we save this in NetworkClientInfo, linked via 'client_id' * which is always an unique number on a server. */ -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CLIENT_INFO) { NetworkClientInfo *ci; ClientID client_id = (ClientID)p->Recv_uint32(); @@ -461,7 +461,7 @@ p->Recv_string(name, sizeof(name)); - if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; ci = NetworkFindClientInfoFromClientID(client_id); if (ci != NULL) { @@ -488,7 +488,7 @@ /* We don't have this client_id yet, find an empty client_id, and put the data there */ ci = new NetworkClientInfo(client_id); ci->client_playas = playas; - if (client_id == _network_own_client_id) MY_CLIENT->SetInfo(ci); + if (client_id == _network_own_client_id) this->SetInfo(ci); strecpy(ci->client_name, name, lastof(ci->client_name)); @@ -497,7 +497,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_ERROR) { NetworkErrorCode error = (NetworkErrorCode)p->Recv_uint8(); @@ -535,7 +535,7 @@ return NETWORK_RECV_STATUS_SERVER_ERROR; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CHECK_NEWGRFS) { uint grf_count = p->Recv_uint8(); NetworkRecvStatus ret = NETWORK_RECV_STATUS_OKAY; @@ -543,7 +543,7 @@ /* Check all GRFs */ for (; grf_count > 0; grf_count--) { GRFIdentifier c; - MY_CLIENT->Recv_GRFIdentifier(p, &c); + this->Recv_GRFIdentifier(p, &c); /* Check whether we know this GRF */ const GRFConfig *f = FindGRFConfig(c.grfid, c.md5sum); @@ -566,7 +566,7 @@ return ret; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_NEED_GAME_PASSWORD) { const char *password = _network_join_server_password; if (!StrEmpty(password)) { @@ -578,11 +578,11 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_NEED_COMPANY_PASSWORD) { _password_game_seed = p->Recv_uint32(); p->Recv_string(_password_server_id, sizeof(_password_server_id)); - if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET; const char *password = _network_join_company_password; if (!StrEmpty(password)) { @@ -594,7 +594,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_WELCOME) { _network_own_client_id = (ClientID)p->Recv_uint32(); @@ -606,7 +606,7 @@ return SEND_COMMAND(PACKET_CLIENT_GETMAP)(); } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WAIT) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_WAIT) { _network_join_status = NETWORK_JOIN_STATUS_WAITING; _network_join_waiting = p->Recv_uint8(); @@ -619,7 +619,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_MAP) { static FILE *file_pointer; @@ -627,7 +627,7 @@ maptype = p->Recv_uint8(); - if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; /* First packet, init some stuff */ if (maptype == MAP_PACKET_START) { @@ -647,7 +647,7 @@ * do a division by zero. When the connection is lost, we just return * that. If kbytes_total is 0, the packet must be malformed as a * savegame less than 1 kilobyte is practically impossible. */ - if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; if (_network_join_bytes_total == 0) return NETWORK_RECV_STATUS_MALFORMED_PACKET; _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING; @@ -708,7 +708,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FRAME) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_FRAME) { _frame_counter_server = p->Recv_uint32(); _frame_counter_max = p->Recv_uint32(); @@ -736,7 +736,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SYNC) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_SYNC) { _sync_frame = p->Recv_uint32(); _sync_seed_1 = p->Recv_uint32(); @@ -747,10 +747,10 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_COMMAND) { CommandPacket cp; - const char *err = MY_CLIENT->Recv_Command(p, &cp); + const char *err = this->Recv_Command(p, &cp); cp.frame = p->Recv_uint32(); cp.my_cmd = p->Recv_bool(); @@ -759,12 +759,12 @@ return NETWORK_RECV_STATUS_MALFORMED_PACKET; } - MY_CLIENT->incoming_queue.Append(&cp); + this->incoming_queue.Append(&cp); return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHAT) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CHAT) { char name[NETWORK_NAME_LENGTH], msg[NETWORK_CHAT_LENGTH]; const NetworkClientInfo *ci = NULL, *ci_to; @@ -814,7 +814,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_ERROR_QUIT) { ClientID client_id = (ClientID)p->Recv_uint32(); @@ -829,7 +829,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_QUIT) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_QUIT) { NetworkClientInfo *ci; @@ -849,7 +849,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_JOIN) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_JOIN) { ClientID client_id = (ClientID)p->Recv_uint32(); @@ -863,14 +863,14 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_SHUTDOWN) { _switch_mode_errorstr = STR_NETWORK_MESSAGE_SERVER_SHUTDOWN; return NETWORK_RECV_STATUS_SERVER_ERROR; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_NEWGAME) { /* To trottle the reconnects a bit, every clients waits * his _local_company value before reconnecting @@ -882,7 +882,7 @@ return NETWORK_RECV_STATUS_SERVER_ERROR; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_RCON) { char rcon_out[NETWORK_RCONCOMMAND_LENGTH]; @@ -894,7 +894,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MOVE) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_MOVE) { /* Nothing more in this packet... */ ClientID client_id = (ClientID)p->Recv_uint32(); @@ -920,7 +920,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CONFIG_UPDATE) { _network_server_max_companies = p->Recv_uint8(); _network_server_max_spectators = p->Recv_uint8(); @@ -928,7 +928,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE) +DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_COMPANY_UPDATE) { _network_company_passworded = p->Recv_uint16(); SetWindowClassesDirty(WC_COMPANY); @@ -936,60 +936,6 @@ return NETWORK_RECV_STATUS_OKAY; } - -/* The layout for the receive-functions by the client */ -typedef NetworkRecvStatus NetworkClientPacket(Packet *p); - -/* This array matches PacketType. At an incoming - * packet it is matches against this array - * and that way the right function to handle that - * packet is found. */ -static NetworkClientPacket * const _network_client_packet[] = { - RECEIVE_COMMAND(PACKET_SERVER_FULL), - RECEIVE_COMMAND(PACKET_SERVER_BANNED), - NULL, // PACKET_CLIENT_JOIN, - RECEIVE_COMMAND(PACKET_SERVER_ERROR), - NULL, // PACKET_CLIENT_COMPANY_INFO, - RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO), - RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO), - RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD), - RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD), - NULL, // PACKET_CLIENT_GAME_PASSWORD, - NULL, // PACKET_CLIENT_COMPANY_PASSWORD, - RECEIVE_COMMAND(PACKET_SERVER_WELCOME), - NULL, // PACKET_CLIENT_GETMAP, - RECEIVE_COMMAND(PACKET_SERVER_WAIT), - RECEIVE_COMMAND(PACKET_SERVER_MAP), - NULL, // PACKET_CLIENT_MAP_OK, - RECEIVE_COMMAND(PACKET_SERVER_JOIN), - RECEIVE_COMMAND(PACKET_SERVER_FRAME), - RECEIVE_COMMAND(PACKET_SERVER_SYNC), - NULL, // PACKET_CLIENT_ACK, - NULL, // PACKET_CLIENT_COMMAND, - RECEIVE_COMMAND(PACKET_SERVER_COMMAND), - NULL, // PACKET_CLIENT_CHAT, - RECEIVE_COMMAND(PACKET_SERVER_CHAT), - NULL, // PACKET_CLIENT_SET_PASSWORD, - NULL, // PACKET_CLIENT_SET_NAME, - NULL, // PACKET_CLIENT_QUIT, - NULL, // PACKET_CLIENT_ERROR, - RECEIVE_COMMAND(PACKET_SERVER_QUIT), - RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT), - RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN), - RECEIVE_COMMAND(PACKET_SERVER_NEWGAME), - RECEIVE_COMMAND(PACKET_SERVER_RCON), - NULL, // PACKET_CLIENT_RCON, - RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS), - NULL, // PACKET_CLIENT_NEWGRFS_CHECKED, - RECEIVE_COMMAND(PACKET_SERVER_MOVE), - NULL, // PACKET_CLIENT_MOVE - RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE), - RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE), -}; - -/* If this fails, check the array above with network_data.h */ -assert_compile(lengthof(_network_client_packet) == PACKET_END); - /* Is called after a client is connected to the server */ void NetworkClient_Connected() { @@ -1001,27 +947,6 @@ SEND_COMMAND(PACKET_CLIENT_JOIN)(); } -/* Reads the packets from the socket-stream, if available */ -NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientSocket *cs) -{ - Packet *p; - NetworkRecvStatus res = NETWORK_RECV_STATUS_OKAY; - - while (res == NETWORK_RECV_STATUS_OKAY && (p = cs->Recv_Packet()) != NULL) { - byte type = p->Recv_uint8(); - if (type < PACKET_END && _network_client_packet[type] != NULL && !MY_CLIENT->HasClientQuit()) { - res = _network_client_packet[type](p); - } else { - res = NETWORK_RECV_STATUS_MALFORMED_PACKET; - DEBUG(net, 0, "[client] received invalid packet type %d", type); - } - - delete p; - } - - return res; -} - void NetworkClientSendRcon(const char *password, const char *command) { SEND_COMMAND(PACKET_CLIENT_RCON)(password, command);
--- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -18,6 +18,31 @@ /** Class for handling the client side of the game connection. */ class ClientNetworkGameSocketHandler : public NetworkGameSocketHandler { +protected: + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FULL); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_BANNED); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WELCOME); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WAIT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MAP); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_JOIN); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FRAME); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SYNC); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMMAND); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHAT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_QUIT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_RCON); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MOVE); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE); public: ClientNetworkGameSocketHandler(SOCKET s); }; @@ -36,7 +61,6 @@ DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command); DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_MOVE)(CompanyID company, const char *pass); -NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientSocket *cs); void NetworkClient_Connected(); extern CompanyID _network_join_as;
--- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -682,37 +682,37 @@ * DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p ************/ -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMPANY_INFO) { - return SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(cs); + return SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(this); } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_NEWGRFS_CHECKED) { - if (cs->status != STATUS_NEWGRFS_CHECK) { + if (this->status != STATUS_NEWGRFS_CHECK) { /* Illegal call, return error and ignore the packet */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } - NetworkClientInfo *ci = cs->GetInfo(); + NetworkClientInfo *ci = this->GetInfo(); /* We now want a password from the client else we do not allow him in! */ if (!StrEmpty(_settings_client.network.server_password)) { - return SEND_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD)(cs); + return SEND_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD)(this); } if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) { - return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(cs); + return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(this); } - return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs); + return SEND_COMMAND(PACKET_SERVER_WELCOME)(this); } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_JOIN) { - if (cs->status != STATUS_INACTIVE) { + if (this->status != STATUS_INACTIVE) { /* Illegal call, return error and ignore the packet */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } char name[NETWORK_CLIENT_NAME_LENGTH]; @@ -726,30 +726,30 @@ /* Check if the client has revision control enabled */ if (!IsNetworkCompatibleVersion(client_revision)) { /* Different revisions!! */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_REVISION); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_WRONG_REVISION); } p->Recv_string(name, sizeof(name)); playas = (Owner)p->Recv_uint8(); client_lang = (NetworkLanguage)p->Recv_uint8(); - if (cs->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; /* join another company does not affect these values */ switch (playas) { case COMPANY_NEW_COMPANY: // New company if (Company::GetNumItems() >= _settings_client.network.max_companies) { - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_FULL); } break; case COMPANY_SPECTATOR: // Spectator if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) { - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_FULL); } break; default: // Join another company (companies 1-8 (index 0-7)) if (!Company::IsValidHumanID(playas)) { - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_COMPANY_MISMATCH); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_COMPANY_MISMATCH); } break; } @@ -759,10 +759,10 @@ if (!NetworkFindName(name)) { // Change name if duplicate /* We could not create a name for this client */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NAME_IN_USE); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NAME_IN_USE); } - ci = cs->GetInfo(); + ci = this->GetInfo(); strecpy(ci->client_name, name, lastof(ci->client_name)); ci->client_playas = playas; @@ -772,20 +772,20 @@ /* Make sure companies to which people try to join are not autocleaned */ if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0; - cs->status = STATUS_NEWGRFS_CHECK; + this->status = STATUS_NEWGRFS_CHECK; if (_grfconfig == NULL) { /* Behave as if we received PACKET_CLIENT_NEWGRFS_CHECKED */ - return RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)(cs, NULL); + return this->RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)(NULL); } - return SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(cs); + return SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(this); } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_GAME_PASSWORD) { - if (cs->status != STATUS_AUTH_GAME) { - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + if (this->status != STATUS_AUTH_GAME) { + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } char password[NETWORK_PASSWORD_LENGTH]; @@ -795,22 +795,22 @@ if (!StrEmpty(_settings_client.network.server_password) && strcmp(password, _settings_client.network.server_password) != 0) { /* Password is invalid */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_WRONG_PASSWORD); } - const NetworkClientInfo *ci = cs->GetInfo(); + const NetworkClientInfo *ci = this->GetInfo(); if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) { - return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(cs); + return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(this); } /* Valid password, allow user */ - return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs); + return SEND_COMMAND(PACKET_SERVER_WELCOME)(this); } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMPANY_PASSWORD) { - if (cs->status != STATUS_AUTH_COMPANY) { - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + if (this->status != STATUS_AUTH_COMPANY) { + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } char password[NETWORK_PASSWORD_LENGTH]; @@ -819,17 +819,17 @@ /* Check company password. Allow joining if we cleared the password meanwhile. * Also, check the company is still valid - client could be moved to spectators * in the middle of the authorization process */ - CompanyID playas = cs->GetInfo()->client_playas; + CompanyID playas = this->GetInfo()->client_playas; if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) && strcmp(password, _network_company_states[playas].password) != 0) { /* Password is invalid */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_WRONG_PASSWORD); } - return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs); + return SEND_COMMAND(PACKET_SERVER_WELCOME)(this); } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_GETMAP) { NetworkClientSocket *new_cs; @@ -844,112 +844,111 @@ if (_openttd_newgrf_version != p->Recv_uint32()) { /* The version we get from the client differs, it must have the * wrong version. The client must be wrong. */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } } else if (p->size != 3) { /* We received a packet from a version that claims to be stable. * That shouldn't happen. The client must be wrong. */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } /* The client was never joined.. so this is impossible, right? * Ignore the packet, give the client a warning, and close his connection */ - if (cs->status < STATUS_AUTHORIZED || cs->HasClientQuit()) { - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED); + if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) { + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_AUTHORIZED); } /* Check if someone else is receiving the map */ FOR_ALL_CLIENT_SOCKETS(new_cs) { if (new_cs->status == STATUS_MAP) { /* Tell the new client to wait */ - cs->status = STATUS_MAP_WAIT; - return SEND_COMMAND(PACKET_SERVER_WAIT)(cs); + this->status = STATUS_MAP_WAIT; + return SEND_COMMAND(PACKET_SERVER_WAIT)(this); } } /* We receive a request to upload the map.. give it to the client! */ - return SEND_COMMAND(PACKET_SERVER_MAP)(cs); + return SEND_COMMAND(PACKET_SERVER_MAP)(this); } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_MAP_OK) { /* Client has the map, now start syncing */ - if (cs->status == STATUS_DONE_MAP && !cs->HasClientQuit()) { + if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) { char client_name[NETWORK_CLIENT_NAME_LENGTH]; NetworkClientSocket *new_cs; - NetworkGetClientName(client_name, sizeof(client_name), cs); + NetworkGetClientName(client_name, sizeof(client_name), this); - NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, NULL, cs->client_id); + NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, NULL, this->client_id); /* Mark the client as pre-active, and wait for an ACK * so we know he is done loading and in sync with us */ - cs->status = STATUS_PRE_ACTIVE; - NetworkHandleCommandQueue(cs); - SEND_COMMAND(PACKET_SERVER_FRAME)(cs); - SEND_COMMAND(PACKET_SERVER_SYNC)(cs); + this->status = STATUS_PRE_ACTIVE; + NetworkHandleCommandQueue(this); + SEND_COMMAND(PACKET_SERVER_FRAME)(this); + SEND_COMMAND(PACKET_SERVER_SYNC)(this); /* This is the frame the client receives * we need it later on to make sure the client is not too slow */ - cs->last_frame = _frame_counter; - cs->last_frame_server = _frame_counter; + this->last_frame = _frame_counter; + this->last_frame_server = _frame_counter; FOR_ALL_CLIENT_SOCKETS(new_cs) { if (new_cs->status > STATUS_AUTHORIZED) { - SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, cs->GetInfo()); - SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->client_id); + SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, this->GetInfo()); + SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, this->client_id); } } /* also update the new client with our max values */ - SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)(cs); + SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)(this); /* quickly update the syncing client with company details */ - return SEND_COMMAND(PACKET_SERVER_COMPANY_UPDATE)(cs); + return SEND_COMMAND(PACKET_SERVER_COMPANY_UPDATE)(this); } /* Wrong status for this packet, give a warning to client, and close connection */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } /** * The client has done a command and wants us to handle it - * @param *cs the connected client that has sent the command - * @param *p the packet in which the command was sent + * @param p the packet in which the command was sent */ -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMMAND) { /* The client was never joined.. so this is impossible, right? * Ignore the packet, give the client a warning, and close his connection */ - if (cs->status < STATUS_DONE_MAP || cs->HasClientQuit()) { - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) { + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } - if (cs->incoming_queue.Count() >= _settings_client.network.max_commands_in_queue) { - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_TOO_MANY_COMMANDS); + if (this->incoming_queue.Count() >= _settings_client.network.max_commands_in_queue) { + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_TOO_MANY_COMMANDS); } CommandPacket cp; - const char *err = cs->Recv_Command(p, &cp); + const char *err = this->Recv_Command(p, &cp); - if (cs->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; - NetworkClientInfo *ci = cs->GetInfo(); + NetworkClientInfo *ci = this->GetInfo(); if (err != NULL) { IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, GetClientIP(ci)); - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) { IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci)); - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_KICKED); } if ((GetCommandFlags(cp.cmd) & CMD_SPECTATOR) == 0 && !Company::IsValidID(cp.company) && ci->client_id != CLIENT_ID_SERVER) { IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci)); - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_KICKED); } /** @@ -960,12 +959,12 @@ if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) { IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...", ci->client_playas + 1, GetClientIP(ci), cp.company + 1); - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_COMPANY_MISMATCH); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_COMPANY_MISMATCH); } if (cp.cmd == CMD_COMPANY_CTRL) { if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) { - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_CHEATER); } /* Check if we are full - else it's possible for spectators to send a CMD_COMPANY_CTRL and the company is created regardless of max_companies! */ @@ -975,13 +974,13 @@ } } - if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = cs->client_id; + if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = this->client_id; - cs->incoming_queue.Append(&cp); + this->incoming_queue.Append(&cp); return NETWORK_RECV_STATUS_OKAY; } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_ERROR) { /* This packets means a client noticed an error and is reporting this * to us. Display the error and report it to the other clients */ @@ -991,12 +990,12 @@ NetworkErrorCode errorno = (NetworkErrorCode)p->Recv_uint8(); /* The client was never joined.. thank the client for the packet, but ignore it */ - if (cs->status < STATUS_DONE_MAP || cs->HasClientQuit()) { - cs->CloseConnection(); + if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) { + this->CloseConnection(); return NETWORK_RECV_STATUS_CONN_LOST; } - NetworkGetClientName(client_name, sizeof(client_name), cs); + NetworkGetClientName(client_name, sizeof(client_name), this); StringID strid = GetNetworkErrorMsg(errorno); GetString(str, strid, lastof(str)); @@ -1007,15 +1006,15 @@ FOR_ALL_CLIENT_SOCKETS(new_cs) { if (new_cs->status > STATUS_AUTHORIZED) { - SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, errorno); + SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, this->client_id, errorno); } } - cs->CloseConnection(false); + this->CloseConnection(false); return NETWORK_RECV_STATUS_CONN_LOST; } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_QUIT) { /* The client wants to leave. Display this and report it to the other * clients. */ @@ -1023,50 +1022,50 @@ char client_name[NETWORK_CLIENT_NAME_LENGTH]; /* The client was never joined.. thank the client for the packet, but ignore it */ - if (cs->status < STATUS_DONE_MAP || cs->HasClientQuit()) { - cs->CloseConnection(); + if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) { + this->CloseConnection(); return NETWORK_RECV_STATUS_CONN_LOST; } - NetworkGetClientName(client_name, sizeof(client_name), cs); + NetworkGetClientName(client_name, sizeof(client_name), this); NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING); FOR_ALL_CLIENT_SOCKETS(new_cs) { if (new_cs->status > STATUS_AUTHORIZED) { - SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->client_id); + SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, this->client_id); } } - cs->CloseConnection(false); + this->CloseConnection(false); return NETWORK_RECV_STATUS_CONN_LOST; } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_ACK) { - if (cs->status < STATUS_AUTHORIZED) { + if (this->status < STATUS_AUTHORIZED) { /* Illegal call, return error and ignore the packet */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_AUTHORIZED); } uint32 frame = p->Recv_uint32(); /* The client is trying to catch up with the server */ - if (cs->status == STATUS_PRE_ACTIVE) { + if (this->status == STATUS_PRE_ACTIVE) { /* The client is not yet catched up? */ if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY; /* Now he is! Unpause the game */ - cs->status = STATUS_ACTIVE; + this->status = STATUS_ACTIVE; /* Execute script for, e.g. MOTD */ IConsoleCmdExec("exec scripts/on_server_connect.scr 0"); } /* The client received the frame, make note of it */ - cs->last_frame = frame; + this->last_frame = frame; /* With those 2 values we can calculate the lag realtime */ - cs->last_frame_server = _frame_counter; + this->last_frame_server = _frame_counter; return NETWORK_RECV_STATUS_OKAY; } @@ -1172,11 +1171,11 @@ } } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_CHAT) { - if (cs->status < STATUS_AUTHORIZED) { + if (this->status < STATUS_AUTHORIZED) { /* Illegal call, return error and ignore the packet */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_AUTHORIZED); } NetworkAction action = (NetworkAction)p->Recv_uint8(); @@ -1187,7 +1186,7 @@ p->Recv_string(msg, NETWORK_CHAT_LENGTH); int64 data = p->Recv_uint64(); - NetworkClientInfo *ci = cs->GetInfo(); + NetworkClientInfo *ci = this->GetInfo(); switch (action) { case NETWORK_ACTION_GIVE_MONEY: if (!Company::IsValidID(ci->client_playas)) break; @@ -1195,28 +1194,28 @@ case NETWORK_ACTION_CHAT: case NETWORK_ACTION_CHAT_CLIENT: case NETWORK_ACTION_CHAT_COMPANY: - NetworkServerSendChat(action, desttype, dest, msg, cs->client_id, data); + NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data); break; default: IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, GetClientIP(ci)); - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); break; } return NETWORK_RECV_STATUS_OKAY; } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_SET_PASSWORD) { - if (cs->status != STATUS_ACTIVE) { + if (this->status != STATUS_ACTIVE) { /* Illegal call, return error and ignore the packet */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } char password[NETWORK_PASSWORD_LENGTH]; const NetworkClientInfo *ci; p->Recv_string(password, sizeof(password)); - ci = cs->GetInfo(); + ci = this->GetInfo(); if (Company::IsValidID(ci->client_playas)) { strecpy(_network_company_states[ci->client_playas].password, password, lastof(_network_company_states[ci->client_playas].password)); @@ -1225,20 +1224,20 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_SET_NAME) { - if (cs->status != STATUS_ACTIVE) { + if (this->status != STATUS_ACTIVE) { /* Illegal call, return error and ignore the packet */ - return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED); } char client_name[NETWORK_CLIENT_NAME_LENGTH]; NetworkClientInfo *ci; p->Recv_string(client_name, sizeof(client_name)); - ci = cs->GetInfo(); + ci = this->GetInfo(); - if (cs->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; + if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; if (ci != NULL) { /* Display change */ @@ -1251,7 +1250,7 @@ return NETWORK_RECV_STATUS_OKAY; } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_RCON) { char pass[NETWORK_PASSWORD_LENGTH]; char command[NETWORK_RCONCOMMAND_LENGTH]; @@ -1262,19 +1261,19 @@ p->Recv_string(command, sizeof(command)); if (strcmp(pass, _settings_client.network.rcon_password) != 0) { - DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->client_id); + DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id); return NETWORK_RECV_STATUS_OKAY; } - DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", cs->client_id, command); + DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command); - _redirect_console_to_client = cs->client_id; + _redirect_console_to_client = this->client_id; IConsoleCmdExec(command); _redirect_console_to_client = INVALID_CLIENT_ID; return NETWORK_RECV_STATUS_OKAY; } -DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MOVE) +DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_MOVE) { CompanyID company_id = (Owner)p->Recv_uint8(); @@ -1289,70 +1288,16 @@ /* Incorrect password sent, return! */ if (strcmp(password, _network_company_states[company_id].password) != 0) { - DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", cs->client_id, company_id + 1); + DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1); return NETWORK_RECV_STATUS_OKAY; } } /* if we get here we can move the client */ - NetworkServerDoMove(cs->client_id, company_id); + NetworkServerDoMove(this->client_id, company_id); return NETWORK_RECV_STATUS_OKAY; } -/* The layout for the receive-functions by the server */ -typedef NetworkRecvStatus NetworkServerPacket(NetworkClientSocket *cs, Packet *p); - - -/* This array matches PacketType. At an incoming - * packet it is matches against this array - * and that way the right function to handle that - * packet is found. */ -static NetworkServerPacket * const _network_server_packet[] = { - NULL, // PACKET_SERVER_FULL, - NULL, // PACKET_SERVER_BANNED, - RECEIVE_COMMAND(PACKET_CLIENT_JOIN), - NULL, // PACKET_SERVER_ERROR, - RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO), - NULL, // PACKET_SERVER_COMPANY_INFO, - NULL, // PACKET_SERVER_CLIENT_INFO, - NULL, // PACKET_SERVER_NEED_GAME_PASSWORD, - NULL, // PACKET_SERVER_NEED_COMPANY_PASSWORD, - RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD), - RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD), - NULL, // PACKET_SERVER_WELCOME, - RECEIVE_COMMAND(PACKET_CLIENT_GETMAP), - NULL, // PACKET_SERVER_WAIT, - NULL, // PACKET_SERVER_MAP, - RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK), - NULL, // PACKET_SERVER_JOIN, - NULL, // PACKET_SERVER_FRAME, - NULL, // PACKET_SERVER_SYNC, - RECEIVE_COMMAND(PACKET_CLIENT_ACK), - RECEIVE_COMMAND(PACKET_CLIENT_COMMAND), - NULL, // PACKET_SERVER_COMMAND, - RECEIVE_COMMAND(PACKET_CLIENT_CHAT), - NULL, // PACKET_SERVER_CHAT, - RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD), - RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME), - RECEIVE_COMMAND(PACKET_CLIENT_QUIT), - RECEIVE_COMMAND(PACKET_CLIENT_ERROR), - NULL, // PACKET_SERVER_QUIT, - NULL, // PACKET_SERVER_ERROR_QUIT, - NULL, // PACKET_SERVER_SHUTDOWN, - NULL, // PACKET_SERVER_NEWGAME, - NULL, // PACKET_SERVER_RCON, - RECEIVE_COMMAND(PACKET_CLIENT_RCON), - NULL, // PACKET_CLIENT_CHECK_NEWGRFS, - RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED), - NULL, // PACKET_SERVER_MOVE, - RECEIVE_COMMAND(PACKET_CLIENT_MOVE), - NULL, // PACKET_SERVER_COMPANY_UPDATE, - NULL, // PACKET_SERVER_CONFIG_UPDATE, -}; - -/* If this fails, check the array above with network_data.h */ -assert_compile(lengthof(_network_server_packet) == PACKET_END); - void NetworkSocketHandler::Send_CompanyInformation(Packet *p, const Company *c, const NetworkCompanyStats *stats) { /* Grab the company name */ @@ -1597,26 +1542,6 @@ return true; } -/* Reads a packet from the stream */ -void NetworkServer_ReadPackets(NetworkClientSocket *cs) -{ - Packet *p; - NetworkRecvStatus res = NETWORK_RECV_STATUS_OKAY; - - while (res == NETWORK_RECV_STATUS_OKAY && (p = cs->Recv_Packet()) != NULL) { - byte type = p->Recv_uint8(); - if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->HasClientQuit()) { - res = _network_server_packet[type](cs, p); - } else { - cs->CloseConnection(); - res = NETWORK_RECV_STATUS_MALFORMED_PACKET; - DEBUG(net, 0, "[server] received invalid packet type %d", type); - } - - delete p; - } -} - /* Handle the local command-queue */ static void NetworkHandleCommandQueue(NetworkClientSocket *cs) {
--- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -18,6 +18,23 @@ /** Class for handling the server side of the game connection. */ class ServerNetworkGameSocketHandler : public NetworkGameSocketHandler { +protected: + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_JOIN); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ACK); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_CHAT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_QUIT); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ERROR); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_RCON); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED); + DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MOVE); public: ServerNetworkGameSocketHandler(SOCKET s); ~ServerNetworkGameSocketHandler();