diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 7c9fc57eab..e4ac63029a 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -3231,6 +3231,14 @@ RelativePath=".\..\src\network\core\tcp.h" > + + + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 3e2c2a6ace..4a8176f679 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -3228,6 +3228,14 @@ RelativePath=".\..\src\network\core\tcp.h" > + + + + diff --git a/source.list b/source.list index a21809fa92..90d0f2872b 100644 --- a/source.list +++ b/source.list @@ -776,6 +776,8 @@ network/core/packet.cpp network/core/packet.h network/core/tcp.cpp network/core/tcp.h +network/core/tcp_game.cpp +network/core/tcp_game.h network/core/udp.cpp network/core/udp.h diff --git a/src/network/core/core.h b/src/network/core/core.h index 272d44adc6..c1605d46dc 100644 --- a/src/network/core/core.h +++ b/src/network/core/core.h @@ -43,7 +43,7 @@ public: SOCKET sock; ///< The socket currently connected to public: /** Create a new unbound socket */ - NetworkSocketHandler() { this->sock = INVALID_SOCKET; this->has_quit = false; } + NetworkSocketHandler(SOCKET s = INVALID_SOCKET) { this->sock = s; this->has_quit = false; } /** Close the socket when distructing the socket handler */ virtual ~NetworkSocketHandler() { this->Close(); } diff --git a/src/network/core/tcp.cpp b/src/network/core/tcp.cpp index 96b6dfbb04..08609ff202 100644 --- a/src/network/core/tcp.cpp +++ b/src/network/core/tcp.cpp @@ -8,31 +8,17 @@ #include "../../stdafx.h" #include "../../debug.h" -#include "../../openttd.h" -#include "../../variables.h" -#include "../network_internal.h" #include "packet.h" #include "tcp.h" -#include "table/strings.h" -#include "../../oldpool_func.h" - -/** Make very sure the preconditions given in network_type.h are actually followed */ -assert_compile(MAX_CLIENT_SLOTS == (MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK) << NCI_BITS_PER_POOL_BLOCK); -assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS); - -typedef ClientIndex NetworkClientSocketID; -DEFINE_OLD_POOL_GENERIC(NetworkClientSocket, NetworkClientSocket); - -NetworkClientSocket::NetworkClientSocket(ClientID client_id) +NetworkTCPSocketHandler::NetworkTCPSocketHandler(SOCKET s) : + NetworkSocketHandler(s), + packet_queue(NULL), packet_recv(NULL), writable(false) { - this->sock = INVALID_SOCKET; - this->client_id = client_id; - this->status = STATUS_INACTIVE; } -NetworkClientSocket::~NetworkClientSocket() +NetworkTCPSocketHandler::~NetworkTCPSocketHandler() { if (this->sock != INVALID_SOCKET) closesocket(this->sock); this->writable = false; @@ -47,39 +33,7 @@ NetworkClientSocket::~NetworkClientSocket() delete this->packet_recv; this->packet_recv = NULL; - while (this->command_queue != NULL) { - CommandPacket *p = this->command_queue->next; - free(this->command_queue); - this->command_queue = p; - } - this->sock = INVALID_SOCKET; - this->client_id = INVALID_CLIENT_ID; - this->status = STATUS_INACTIVE; -} - -/** - * Functions to help NetworkRecv_Packet/NetworkSend_Packet a bit - * A socket can make errors. When that happens this handles what to do. - * For clients: close connection and drop back to main-menu - * For servers: close connection and that is it - * @return the new status - * TODO: needs to be splitted when using client and server socket packets - */ -NetworkRecvStatus NetworkClientSocket::CloseConnection() -{ - /* Clients drop back to the main menu */ - if (!_network_server && _networking) { - _switch_mode = SM_MENU; - _networking = false; - extern StringID _switch_mode_errorstr; - _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION; - - return NETWORK_RECV_STATUS_CONN_LOST; - } - - NetworkCloseClient(this); - return NETWORK_RECV_STATUS_OKAY; } /** @@ -88,7 +42,7 @@ NetworkRecvStatus NetworkClientSocket::CloseConnection() * if the OS-network-buffer is full) * @param packet the packet to send */ -void NetworkClientSocket::Send_Packet(Packet *packet) +void NetworkTCPSocketHandler::Send_Packet(Packet *packet) { Packet *p; assert(packet != NULL); @@ -114,7 +68,7 @@ void NetworkClientSocket::Send_Packet(Packet *packet) * data right now (full network-buffer, it happens ;)) * 3) sending took too long */ -bool NetworkClientSocket::Send_Packets() +bool NetworkTCPSocketHandler::Send_Packets() { ssize_t res; Packet *p; @@ -163,7 +117,7 @@ bool NetworkClientSocket::Send_Packets() * @param status the variable to store the status into * @return the received packet (or NULL when it didn't receive one) */ -Packet *NetworkClientSocket::Recv_Packet(NetworkRecvStatus *status) +Packet *NetworkTCPSocketHandler::Recv_Packet(NetworkRecvStatus *status) { ssize_t res; Packet *p; @@ -242,7 +196,7 @@ Packet *NetworkClientSocket::Recv_Packet(NetworkRecvStatus *status) return p; } -bool NetworkClientSocket::IsPacketQueueEmpty() +bool NetworkTCPSocketHandler::IsPacketQueueEmpty() { return this->packet_queue == NULL; } diff --git a/src/network/core/tcp.h b/src/network/core/tcp.h index a124337a01..da3a55adf9 100644 --- a/src/network/core/tcp.h +++ b/src/network/core/tcp.h @@ -13,114 +13,24 @@ #include "core.h" #include "packet.h" -/** - * Enum with all types of UDP packets. - * The order of the first 4 packets MUST not be changed, as - * it protects old clients from joining newer servers - * (because SERVER_ERROR is the respond to a wrong revision) - */ -enum { - PACKET_SERVER_FULL, - PACKET_SERVER_BANNED, - PACKET_CLIENT_JOIN, - PACKET_SERVER_ERROR, - PACKET_CLIENT_COMPANY_INFO, - PACKET_SERVER_COMPANY_INFO, - PACKET_SERVER_CLIENT_INFO, - PACKET_SERVER_NEED_PASSWORD, - PACKET_CLIENT_PASSWORD, - PACKET_SERVER_WELCOME, - PACKET_CLIENT_GETMAP, - PACKET_SERVER_WAIT, - PACKET_SERVER_MAP, - PACKET_CLIENT_MAP_OK, - PACKET_SERVER_JOIN, - PACKET_SERVER_FRAME, - PACKET_SERVER_SYNC, - PACKET_CLIENT_ACK, - PACKET_CLIENT_COMMAND, - PACKET_SERVER_COMMAND, - PACKET_CLIENT_CHAT, - PACKET_SERVER_CHAT, - PACKET_CLIENT_SET_PASSWORD, - PACKET_CLIENT_SET_NAME, - PACKET_CLIENT_QUIT, - PACKET_CLIENT_ERROR, - PACKET_SERVER_QUIT, - PACKET_SERVER_ERROR_QUIT, - PACKET_SERVER_SHUTDOWN, - PACKET_SERVER_NEWGAME, - PACKET_SERVER_RCON, - PACKET_CLIENT_RCON, - PACKET_SERVER_CHECK_NEWGRFS, - PACKET_CLIENT_NEWGRFS_CHECKED, - PACKET_END ///< Must ALWAYS be on the end of this list!! (period) -}; - -/** Packet that wraps a command */ -struct CommandPacket; - -/** Status of a client */ -enum ClientStatus { - STATUS_INACTIVE, ///< The client is not connected nor active - STATUS_AUTHORIZING,///< The client is authorizing - STATUS_AUTH, ///< The client is authorized - STATUS_MAP_WAIT, ///< The client is waiting as someone else is downloading the map - STATUS_MAP, ///< The client is downloading the map - STATUS_DONE_MAP, ///< The client has downloaded the map - STATUS_PRE_ACTIVE, ///< The client is catching up the delayed frames - STATUS_ACTIVE, ///< The client is active within in the game -}; - - -class NetworkClientSocket; -DECLARE_OLD_POOL(NetworkClientSocket, NetworkClientSocket, NCI_BITS_PER_POOL_BLOCK, MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK); - /** Base socket handler for all TCP sockets */ -class NetworkClientSocket : public PoolItem, public NetworkSocketHandler { -/* TODO: rewrite into a proper class */ +class NetworkTCPSocketHandler : public NetworkSocketHandler { private: Packet *packet_queue; ///< Packets that are awaiting delivery Packet *packet_recv; ///< Partially received packet - NetworkClientInfo *info; ///< Client info related to this socket public: - ClientID client_id; ///< Client identifier - uint32 last_frame; ///< Last frame we have executed - uint32 last_frame_server; ///< Last frame the server has executed - byte lag_test; ///< Byte used for lag-testing the client - - ClientStatus status; ///< Status of this client bool writable; ///< Can we write to this socket? - CommandPacket *command_queue; ///< The command-queue awaiting delivery - - NetworkRecvStatus CloseConnection(); - void Send_Packet(Packet *packet); bool Send_Packets(); bool IsPacketQueueEmpty(); Packet *Recv_Packet(NetworkRecvStatus *status); - NetworkClientSocket(ClientID client_id = INVALID_CLIENT_ID); - ~NetworkClientSocket(); - - inline bool IsValid() const { return this->IsConnected(); } - inline void SetInfo(NetworkClientInfo *info) { assert(info != NULL && this->info == NULL); this->info = info; } - inline NetworkClientInfo *GetInfo() const { return this->info; } - - const char *Recv_Command(Packet *p, CommandPacket *cp); - void Send_Command(Packet *p, const CommandPacket *cp); + NetworkTCPSocketHandler(SOCKET s = INVALID_SOCKET); + ~NetworkTCPSocketHandler(); }; -static inline bool IsValidNetworkClientSocketIndex(ClientIndex index) -{ - return (uint)index < GetNetworkClientSocketPoolSize() && GetNetworkClientSocket(index)->IsValid(); -} - -#define FOR_ALL_CLIENT_SOCKETS_FROM(d, start) for (d = GetNetworkClientSocket(start); d != NULL; d = (d->index + 1U < GetNetworkClientSocketPoolSize()) ? GetNetworkClientSocket(d->index + 1U) : NULL) if (d->IsValid()) -#define FOR_ALL_CLIENT_SOCKETS(d) FOR_ALL_CLIENT_SOCKETS_FROM(d, 0) - #endif /* ENABLE_NETWORK */ #endif /* NETWORK_CORE_TCP_H */ diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp new file mode 100644 index 0000000000..d34ace4bf7 --- /dev/null +++ b/src/network/core/tcp_game.cpp @@ -0,0 +1,69 @@ +/* $Id$ */ + +/** + * @file tcp_game.cpp Basic functions to receive and send TCP packets for game purposes. + */ + +#ifdef ENABLE_NETWORK + +#include "../../stdafx.h" +#include "../../openttd.h" +#include "../../variables.h" + +#include "../network_internal.h" +#include "packet.h" +#include "tcp_game.h" + +#include "table/strings.h" +#include "../../oldpool_func.h" + +/** Make very sure the preconditions given in network_type.h are actually followed */ +assert_compile(MAX_CLIENT_SLOTS == (MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK) << NCI_BITS_PER_POOL_BLOCK); +assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS); + +typedef ClientIndex NetworkClientSocketID; +DEFINE_OLD_POOL_GENERIC(NetworkClientSocket, NetworkClientSocket); + +NetworkClientSocket::NetworkClientSocket(ClientID client_id) +{ + this->client_id = client_id; + this->status = STATUS_INACTIVE; +} + +NetworkClientSocket::~NetworkClientSocket() +{ + while (this->command_queue != NULL) { + CommandPacket *p = this->command_queue->next; + free(this->command_queue); + this->command_queue = p; + } + + this->client_id = INVALID_CLIENT_ID; + this->status = STATUS_INACTIVE; +} + +/** + * Functions to help NetworkRecv_Packet/NetworkSend_Packet a bit + * A socket can make errors. When that happens this handles what to do. + * For clients: close connection and drop back to main-menu + * For servers: close connection and that is it + * @return the new status + * TODO: needs to be splitted when using client and server socket packets + */ +NetworkRecvStatus NetworkClientSocket::CloseConnection() +{ + /* Clients drop back to the main menu */ + if (!_network_server && _networking) { + _switch_mode = SM_MENU; + _networking = false; + extern StringID _switch_mode_errorstr; + _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION; + + return NETWORK_RECV_STATUS_CONN_LOST; + } + + NetworkCloseClient(this); + return NETWORK_RECV_STATUS_OKAY; +} + +#endif /* ENABLE_NETWORK */ diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h new file mode 100644 index 0000000000..1c0f047eac --- /dev/null +++ b/src/network/core/tcp_game.h @@ -0,0 +1,117 @@ +/* $Id$ */ + +/** + * @file tcp_game.h Basic functions to receive and send TCP packets for game purposes. + */ + +#ifndef NETWORK_CORE_TCP_GAME_H +#define NETWORK_CORE_TCP_GAME_H + +#ifdef ENABLE_NETWORK + +#include "os_abstraction.h" +#include "tcp.h" +#include "packet.h" + +/** + * Enum with all types of UDP packets. + * The order of the first 4 packets MUST not be changed, as + * it protects old clients from joining newer servers + * (because SERVER_ERROR is the respond to a wrong revision) + */ +enum { + PACKET_SERVER_FULL, + PACKET_SERVER_BANNED, + PACKET_CLIENT_JOIN, + PACKET_SERVER_ERROR, + PACKET_CLIENT_COMPANY_INFO, + PACKET_SERVER_COMPANY_INFO, + PACKET_SERVER_CLIENT_INFO, + PACKET_SERVER_NEED_PASSWORD, + PACKET_CLIENT_PASSWORD, + PACKET_SERVER_WELCOME, + PACKET_CLIENT_GETMAP, + PACKET_SERVER_WAIT, + PACKET_SERVER_MAP, + PACKET_CLIENT_MAP_OK, + PACKET_SERVER_JOIN, + PACKET_SERVER_FRAME, + PACKET_SERVER_SYNC, + PACKET_CLIENT_ACK, + PACKET_CLIENT_COMMAND, + PACKET_SERVER_COMMAND, + PACKET_CLIENT_CHAT, + PACKET_SERVER_CHAT, + PACKET_CLIENT_SET_PASSWORD, + PACKET_CLIENT_SET_NAME, + PACKET_CLIENT_QUIT, + PACKET_CLIENT_ERROR, + PACKET_SERVER_QUIT, + PACKET_SERVER_ERROR_QUIT, + PACKET_SERVER_SHUTDOWN, + PACKET_SERVER_NEWGAME, + PACKET_SERVER_RCON, + PACKET_CLIENT_RCON, + PACKET_SERVER_CHECK_NEWGRFS, + PACKET_CLIENT_NEWGRFS_CHECKED, + PACKET_END ///< Must ALWAYS be on the end of this list!! (period) +}; + +/** Packet that wraps a command */ +struct CommandPacket; + +/** Status of a client */ +enum ClientStatus { + STATUS_INACTIVE, ///< The client is not connected nor active + STATUS_AUTHORIZING,///< The client is authorizing + STATUS_AUTH, ///< The client is authorized + STATUS_MAP_WAIT, ///< The client is waiting as someone else is downloading the map + STATUS_MAP, ///< The client is downloading the map + STATUS_DONE_MAP, ///< The client has downloaded the map + STATUS_PRE_ACTIVE, ///< The client is catching up the delayed frames + STATUS_ACTIVE, ///< The client is active within in the game +}; + + +class NetworkClientSocket; +DECLARE_OLD_POOL(NetworkClientSocket, NetworkClientSocket, NCI_BITS_PER_POOL_BLOCK, MAX_CLIENT_SLOTS >> NCI_BITS_PER_POOL_BLOCK); + +/** Base socket handler for all TCP sockets */ +class NetworkClientSocket : public PoolItem, public NetworkTCPSocketHandler { +/* TODO: rewrite into a proper class */ +private: + NetworkClientInfo *info; ///< Client info related to this socket +public: + ClientID client_id; ///< Client identifier + uint32 last_frame; ///< Last frame we have executed + uint32 last_frame_server; ///< Last frame the server has executed + byte lag_test; ///< Byte used for lag-testing the client + + ClientStatus status; ///< Status of this client + + CommandPacket *command_queue; ///< The command-queue awaiting delivery + + NetworkRecvStatus CloseConnection(); + + NetworkClientSocket(ClientID client_id = INVALID_CLIENT_ID); + ~NetworkClientSocket(); + + inline bool IsValid() const { return this->IsConnected(); } + inline void SetInfo(NetworkClientInfo *info) { assert(info != NULL && this->info == NULL); this->info = info; } + inline NetworkClientInfo *GetInfo() const { return this->info; } + + const char *Recv_Command(Packet *p, CommandPacket *cp); + void Send_Command(Packet *p, const CommandPacket *cp); +}; + +static inline bool IsValidNetworkClientSocketIndex(ClientIndex index) +{ + return (uint)index < GetNetworkClientSocketPoolSize() && GetNetworkClientSocket(index)->IsValid(); +} + +#define FOR_ALL_CLIENT_SOCKETS_FROM(d, start) for (d = GetNetworkClientSocket(start); d != NULL; d = (d->index + 1U < GetNetworkClientSocketPoolSize()) ? GetNetworkClientSocket(d->index + 1U) : NULL) if (d->IsValid()) +#define FOR_ALL_CLIENT_SOCKETS(d) FOR_ALL_CLIENT_SOCKETS_FROM(d, 0) + +#endif /* ENABLE_NETWORK */ + +#endif /* NETWORK_CORE_TCP_GAME_H */ diff --git a/src/network/network_internal.h b/src/network/network_internal.h index 05e373959e..59b12a9db2 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -14,7 +14,7 @@ #include "core/core.h" #include "core/config.h" #include "core/packet.h" -#include "core/tcp.h" +#include "core/tcp_game.h" #include "../command_type.h"