summaryrefslogtreecommitdiff
path: root/src/network/core/tcp_game.h
blob: 77da6218cff85515742ebabee8b3ba9fed35c9eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* $Id$ */

/*
 * This file is part of OpenTTD.
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @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

#include "os_abstraction.h"
#include "tcp.h"
#include "../network_type.h"
#include "../../core/pool_type.hpp"

#ifdef ENABLE_NETWORK

/**
 * 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 TCPPacketType {
	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_GAME_PASSWORD,
	PACKET_SERVER_NEED_COMPANY_PASSWORD,
	PACKET_CLIENT_GAME_PASSWORD,
	PACKET_CLIENT_COMPANY_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_SERVER_MOVE,
	PACKET_CLIENT_MOVE,
	PACKET_SERVER_COMPANY_UPDATE,
	PACKET_SERVER_CONFIG_UPDATE,
	PACKET_END                   ///< Must ALWAYS be on the end of this list!! (period)
};

/** Packet that wraps a command */
struct CommandPacket;

/** A queue of CommandPackets. */
class CommandQueue {
	CommandPacket *first; ///< The first packet in the queue.
	CommandPacket *last;  ///< The last packet in the queue; only valid when first != NULL.
	uint count;           ///< The number of items in the queue.

public:
	/** Initialise the command queue. */
	CommandQueue() : first(NULL), last(NULL) {}
	/** Clear the command queue. */
	~CommandQueue() { this->Free(); }
	void Append(CommandPacket *p);
	CommandPacket *Pop();
	CommandPacket *Peek();
	void Free();
	/** Get the number of items in the queue. */
	uint Count() const { return this->count; }
};

/** Status of a client */
enum ClientStatus {
	STATUS_INACTIVE,     ///< The client is not connected nor active
	STATUS_NEWGRFS_CHECK, ///< The client is checking NewGRFs
	STATUS_AUTH_GAME,    ///< The client is authorizing with game (server) password
	STATUS_AUTH_COMPANY, ///< The client is authorizing with company password
	STATUS_AUTHORIZED,   ///< 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
	STATUS_END           ///< Must ALWAYS be on the end of this list!! (period)
};

class NetworkGameSocketHandler;
typedef NetworkGameSocketHandler NetworkClientSocket;
typedef Pool<NetworkClientSocket, ClientIndex, 8, MAX_CLIENT_SLOTS> NetworkClientSocketPool;
extern NetworkClientSocketPool _networkclientsocket_pool;

/** 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:
	NetworkGameSocketHandler(SOCKET s);
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

	CommandQueue incoming_queue; ///< The command-queue awaiting handling
	CommandQueue outgoing_queue; ///< The command-queue awaiting delivery

	NetworkRecvStatus CloseConnection(bool error = true);
	virtual ~NetworkGameSocketHandler() {}

	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);
};

#define FOR_ALL_CLIENT_SOCKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(NetworkClientSocket, clientsocket_index, var, start)
#define FOR_ALL_CLIENT_SOCKETS(var) FOR_ALL_CLIENT_SOCKETS_FROM(var, 0)

#endif /* ENABLE_NETWORK */

#endif /* NETWORK_CORE_TCP_GAME_H */