rubidium@5720: /* $Id$ */ rubidium@5720: rubidium@5720: /** rubidium@5720: * @file udp.h Basic functions to receive and send UDP packets. rubidium@5796: * rubidium@5796: * rubidium@5796: * *** Requesting game information from a server *** rubidium@5796: * rubidium@5796: * This describes the on-the-wire structure of the request and reply rubidium@5796: * packet of the NetworkGameInfo (see game.h) data. rubidium@5796: * rubidium@5796: * --- Points of attention --- rubidium@5796: * - all > 1 byte integral values are written in little endian, rubidium@5796: * unless specified otherwise. rubidium@5796: * Thus, 0x01234567 would be sent as {0x67, 0x45, 0x23, 0x01}. rubidium@5796: * - all sent strings are of variable length and terminated by a '\0'. rubidium@5796: * Thus, the length of the strings is not sent. rubidium@5796: * - years that are leap years in the 'days since X' to 'date' calculations: rubidium@5796: * (year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0)) rubidium@5796: * rubidium@5796: * --- Request --- rubidium@5796: * Bytes: Description: rubidium@5796: * 2 size of the whole packet, in this case 3 rubidium@5796: * 1 type of packet, in this case PACKET_UDP_CLIENT_FIND_SERVER (0) rubidium@5796: * This packet would look like: { 0x03, 0x00, 0x00 } rubidium@5796: * rubidium@5796: * --- Reply --- rubidium@5796: * Version: Bytes: Description: rubidium@5796: * all 2 size of the whole packet rubidium@5796: * all 1 type of packet, in this case PACKET_UDP_SERVER_RESPONSE (1) rubidium@5796: * all 1 the version of this packet's structure rubidium@5796: * rubidium@5796: * 4+ 1 number of GRFs attached (n) rubidium@5796: * 4+ n * 20 unique identifier for GRF files. Constists of: rubidium@5796: * - one 4 byte variable with the GRF ID rubidium@5796: * - 16 bytes (sent sequentially) for the MD5 checksum rubidium@5796: * of the GRF rubidium@5796: * rubidium@5796: * 3+ 4 current game date in days since 1-1-0 (DMY) rubidium@5796: * 3+ 4 game introduction date in days since 1-1-0 (DMY) rubidium@5796: * rubidium@5796: * 2+ 1 maximum number of companies allowed on the server rubidium@5796: * 2+ 1 number of companies on the server rubidium@5796: * 2+ 1 maximum number of spectators allowed on the server rubidium@5796: * rubidium@5796: * 1+ var string with the name of the server rubidium@5796: * 1+ var string with the revision of the server rubidium@5796: * 1+ 1 the language run on the server rubidium@5796: * (0 = any, 1 = English, 2 = German, 3 = French) rubidium@5796: * 1+ 1 whether the server uses a password (0 = no, 1 = yes) rubidium@5796: * 1+ 1 maximum number of clients allowed on the server rubidium@5796: * 1+ 1 number of clients on the server rubidium@5796: * 1+ 1 number of spectators on the server rubidium@5796: * 1 & 2 2 current game date in days since 1-1-1920 (DMY) rubidium@5796: * 1 & 2 2 game introduction date in days since 1-1-1920 (DMY) rubidium@5796: * 1+ var string with the name of the map rubidium@5796: * 1+ 2 width of the map in tiles rubidium@5796: * 1+ 2 height of the map in tiles rubidium@5796: * 1+ 1 type of map: rubidium@5796: * (0 = temperate, 1 = arctic, 2 = desert, 3 = toyland) rubidium@5796: * 1+ 1 whether the server is dedicated (0 = no, 1 = yes) rubidium@5720: */ rubidium@5720: celestar@6447: #ifndef NETWORK_CORE_UDP_H celestar@6447: #define NETWORK_CORE_UDP_H celestar@6447: celestar@6447: #ifdef ENABLE_NETWORK celestar@6447: celestar@6447: #include "os_abstraction.h" celestar@6447: #include "core.h" celestar@6447: #include "game.h" celestar@6447: #include "packet.h" celestar@6447: #include "../../debug.h" celestar@6447: rubidium@5720: /** Enum with all types of UDP packets. The order MUST not be changed **/ rubidium@5870: enum PacketUDPType { rubidium@5720: PACKET_UDP_CLIENT_FIND_SERVER, ///< Queries a game server for game information rubidium@5720: PACKET_UDP_SERVER_RESPONSE, ///< Reply of the game server with game information rubidium@5720: PACKET_UDP_CLIENT_DETAIL_INFO, ///< Queries a game server about details of the game, such as companies rubidium@5720: PACKET_UDP_SERVER_DETAIL_INFO, ///< Reply of the game server about details of the game, such as companies rubidium@5720: PACKET_UDP_SERVER_REGISTER, ///< Packet to register itself to the master server rubidium@5720: PACKET_UDP_MASTER_ACK_REGISTER, ///< Packet indicating registration has succedeed rubidium@5720: PACKET_UDP_CLIENT_GET_LIST, ///< Request for serverlist from master server rubidium@5720: PACKET_UDP_MASTER_RESPONSE_LIST, ///< Response from master server with server ip's + port's rubidium@5720: PACKET_UDP_SERVER_UNREGISTER, ///< Request to be removed from the server-list rubidium@5720: PACKET_UDP_CLIENT_GET_NEWGRFS, ///< Requests the name for a list of GRFs (GRF_ID and MD5) rubidium@5720: PACKET_UDP_SERVER_NEWGRFS, ///< Sends the list of NewGRF's requested. rubidium@5720: PACKET_UDP_END ///< Must ALWAYS be on the end of this list!! (period) rubidium@5720: }; rubidium@5720: rubidium@5870: #define DECLARE_UDP_RECEIVE_COMMAND(type) virtual void NetworkPacketReceive_## type ##_command(Packet *p, const struct sockaddr_in *) rubidium@6112: #define DEF_UDP_RECEIVE_COMMAND(cls, type) void cls ##NetworkUDPSocketHandler::NetworkPacketReceive_ ## type ## _command(Packet *p, const struct sockaddr_in *client_addr) rubidium@5720: rubidium@5875: /** Base socket handler for all UDP sockets */ rubidium@5875: class NetworkUDPSocketHandler : public NetworkSocketHandler { rubidium@5870: protected: rubidium@5875: NetworkRecvStatus CloseConnection(); rubidium@5875: rubidium@5870: /* Declare all possible packets here. If it can be received by the rubidium@5870: * a specific handler, it has to be implemented. */ rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_DETAIL_INFO); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_REGISTER); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_LIST); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_UNREGISTER); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS); rubidium@5870: DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS); rubidium@5870: rubidium@5870: void HandleUDPPacket(Packet *p, const struct sockaddr_in *client_addr); rubidium@5870: rubidium@5870: /** rubidium@5870: * Function that is called for every GRFConfig that is read when receiving rubidium@5870: * a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This rubidium@5870: * function must set all appropriate fields. This GRF is later appended to rubidium@5870: * the grfconfig list of the NetworkGameInfo. rubidium@5870: * @param config the GRF to handle rubidium@5870: */ rubidium@6116: virtual void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config) { NOT_REACHED(); } rubidium@5870: public: rubidium@6115: /** On destructing of this class, the socket needs to be closed */ rubidium@5870: virtual ~NetworkUDPSocketHandler() { this->Close(); } rubidium@5870: rubidium@5870: bool Listen(uint32 host, uint16 port, bool broadcast); rubidium@5870: void Close(); rubidium@5870: rubidium@5870: void SendPacket(Packet *p, const struct sockaddr_in *recv); rubidium@5870: void ReceivePackets(); rubidium@5870: rubidium@5870: void Send_NetworkGameInfo(Packet *p, const NetworkGameInfo *info); rubidium@5870: void Recv_NetworkGameInfo(Packet *p, NetworkGameInfo *info); rubidium@5870: }; rubidium@5720: rubidium@5720: #endif /* ENABLE_NETWORK */ rubidium@5720: rubidium@5720: #endif /* NETWORK_CORE_UDP_H */