4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
11 * @file tcp_game.cpp Basic functions to receive and send TCP packets for game purposes.
16 #include "../../stdafx.h"
18 #include "../network.h"
19 #include "../network_internal.h"
20 #include "../../debug.h"
21 #include "../../error.h"
23 #include "table/strings.h"
25 #include "../../safeguards.h"
28 * Create a new socket for the game connection.
29 * @param s The socket to connect with.
31 NetworkGameSocketHandler::NetworkGameSocketHandler(SOCKET s
) : info(NULL
), client_id(INVALID_CLIENT_ID
),
32 last_frame(_frame_counter
), last_frame_server(_frame_counter
), last_packet(_realtime_tick
)
38 * Functions to help ReceivePacket/SendPacket a bit
39 * A socket can make errors. When that happens this handles what to do.
40 * For clients: close connection and drop back to main-menu
41 * For servers: close connection and that is it
42 * @return the new status
44 NetworkRecvStatus
NetworkGameSocketHandler::CloseConnection(bool error
)
46 /* Clients drop back to the main menu */
47 if (!_network_server
&& _networking
) {
48 _switch_mode
= SM_MENU
;
50 ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION
, INVALID_STRING_ID
, WL_CRITICAL
);
52 return NETWORK_RECV_STATUS_CONN_LOST
;
55 return this->CloseConnection(error
? NETWORK_RECV_STATUS_SERVER_ERROR
: NETWORK_RECV_STATUS_CONN_LOST
);
60 * Handle the given packet, i.e. pass it to the right parser receive command.
61 * @param p the packet to handle
62 * @return #NetworkRecvStatus of handling.
64 NetworkRecvStatus
NetworkGameSocketHandler::HandlePacket(Packet
*p
)
66 PacketGameType type
= (PacketGameType
)p
->Recv_uint8();
68 this->last_packet
= _realtime_tick
;
70 switch (this->HasClientQuit() ? PACKET_END
: type
) {
71 case PACKET_SERVER_FULL
: return this->Receive_SERVER_FULL(p
);
72 case PACKET_SERVER_BANNED
: return this->Receive_SERVER_BANNED(p
);
73 case PACKET_CLIENT_JOIN
: return this->Receive_CLIENT_JOIN(p
);
74 case PACKET_SERVER_ERROR
: return this->Receive_SERVER_ERROR(p
);
75 case PACKET_CLIENT_COMPANY_INFO
: return this->Receive_CLIENT_COMPANY_INFO(p
);
76 case PACKET_SERVER_COMPANY_INFO
: return this->Receive_SERVER_COMPANY_INFO(p
);
77 case PACKET_SERVER_CLIENT_INFO
: return this->Receive_SERVER_CLIENT_INFO(p
);
78 case PACKET_SERVER_NEED_GAME_PASSWORD
: return this->Receive_SERVER_NEED_GAME_PASSWORD(p
);
79 case PACKET_SERVER_NEED_COMPANY_PASSWORD
: return this->Receive_SERVER_NEED_COMPANY_PASSWORD(p
);
80 case PACKET_CLIENT_GAME_PASSWORD
: return this->Receive_CLIENT_GAME_PASSWORD(p
);
81 case PACKET_CLIENT_COMPANY_PASSWORD
: return this->Receive_CLIENT_COMPANY_PASSWORD(p
);
82 case PACKET_SERVER_WELCOME
: return this->Receive_SERVER_WELCOME(p
);
83 case PACKET_CLIENT_GETMAP
: return this->Receive_CLIENT_GETMAP(p
);
84 case PACKET_SERVER_WAIT
: return this->Receive_SERVER_WAIT(p
);
85 case PACKET_SERVER_MAP_BEGIN
: return this->Receive_SERVER_MAP_BEGIN(p
);
86 case PACKET_SERVER_MAP_SIZE
: return this->Receive_SERVER_MAP_SIZE(p
);
87 case PACKET_SERVER_MAP_DATA
: return this->Receive_SERVER_MAP_DATA(p
);
88 case PACKET_SERVER_MAP_DONE
: return this->Receive_SERVER_MAP_DONE(p
);
89 case PACKET_CLIENT_MAP_OK
: return this->Receive_CLIENT_MAP_OK(p
);
90 case PACKET_SERVER_JOIN
: return this->Receive_SERVER_JOIN(p
);
91 case PACKET_SERVER_FRAME
: return this->Receive_SERVER_FRAME(p
);
92 case PACKET_SERVER_SYNC
: return this->Receive_SERVER_SYNC(p
);
93 case PACKET_CLIENT_ACK
: return this->Receive_CLIENT_ACK(p
);
94 case PACKET_CLIENT_COMMAND
: return this->Receive_CLIENT_COMMAND(p
);
95 case PACKET_SERVER_COMMAND
: return this->Receive_SERVER_COMMAND(p
);
96 case PACKET_CLIENT_CHAT
: return this->Receive_CLIENT_CHAT(p
);
97 case PACKET_SERVER_CHAT
: return this->Receive_SERVER_CHAT(p
);
98 case PACKET_CLIENT_SET_PASSWORD
: return this->Receive_CLIENT_SET_PASSWORD(p
);
99 case PACKET_CLIENT_SET_NAME
: return this->Receive_CLIENT_SET_NAME(p
);
100 case PACKET_CLIENT_QUIT
: return this->Receive_CLIENT_QUIT(p
);
101 case PACKET_CLIENT_ERROR
: return this->Receive_CLIENT_ERROR(p
);
102 case PACKET_SERVER_QUIT
: return this->Receive_SERVER_QUIT(p
);
103 case PACKET_SERVER_ERROR_QUIT
: return this->Receive_SERVER_ERROR_QUIT(p
);
104 case PACKET_SERVER_SHUTDOWN
: return this->Receive_SERVER_SHUTDOWN(p
);
105 case PACKET_SERVER_NEWGAME
: return this->Receive_SERVER_NEWGAME(p
);
106 case PACKET_SERVER_RCON
: return this->Receive_SERVER_RCON(p
);
107 case PACKET_CLIENT_RCON
: return this->Receive_CLIENT_RCON(p
);
108 case PACKET_SERVER_CHECK_NEWGRFS
: return this->Receive_SERVER_CHECK_NEWGRFS(p
);
109 case PACKET_CLIENT_NEWGRFS_CHECKED
: return this->Receive_CLIENT_NEWGRFS_CHECKED(p
);
110 case PACKET_SERVER_MOVE
: return this->Receive_SERVER_MOVE(p
);
111 case PACKET_CLIENT_MOVE
: return this->Receive_CLIENT_MOVE(p
);
112 case PACKET_SERVER_COMPANY_UPDATE
: return this->Receive_SERVER_COMPANY_UPDATE(p
);
113 case PACKET_SERVER_CONFIG_UPDATE
: return this->Receive_SERVER_CONFIG_UPDATE(p
);
116 this->CloseConnection();
118 if (this->HasClientQuit()) {
119 DEBUG(net
, 0, "[tcp/game] received invalid packet type %d from client %d", type
, this->client_id
);
121 DEBUG(net
, 0, "[tcp/game] received illegal packet from client %d", this->client_id
);
123 return NETWORK_RECV_STATUS_MALFORMED_PACKET
;
128 * Do the actual receiving of packets.
129 * As long as HandlePacket returns OKAY packets are handled. Upon
130 * failure, or no more packets to process the last result of
131 * HandlePacket is returned.
132 * @return #NetworkRecvStatus of the last handled packet.
134 NetworkRecvStatus
NetworkGameSocketHandler::ReceivePackets()
137 while ((p
= this->ReceivePacket()) != NULL
) {
138 NetworkRecvStatus res
= HandlePacket(p
);
140 if (res
!= NETWORK_RECV_STATUS_OKAY
) return res
;
143 return NETWORK_RECV_STATUS_OKAY
;
147 * Helper for logging receiving invalid packets.
148 * @param type The received packet type.
149 * @return The status the network should have, in this case: "malformed packet error".
151 NetworkRecvStatus
NetworkGameSocketHandler::ReceiveInvalidPacket(PacketGameType type
)
153 DEBUG(net
, 0, "[tcp/game] received illegal packet type %d from client %d", type
, this->client_id
);
154 return NETWORK_RECV_STATUS_MALFORMED_PACKET
;
157 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_FULL(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_FULL
); }
158 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_BANNED(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_BANNED
); }
159 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_JOIN
); }
160 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_ERROR(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_ERROR
); }
161 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMPANY_INFO
); }
162 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMPANY_INFO
); }
163 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_CLIENT_INFO
); }
164 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_NEED_GAME_PASSWORD(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_NEED_GAME_PASSWORD
); }
165 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PASSWORD(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_NEED_COMPANY_PASSWORD
); }
166 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_GAME_PASSWORD(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GAME_PASSWORD
); }
167 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_COMPANY_PASSWORD(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMPANY_PASSWORD
); }
168 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_WELCOME(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_WELCOME
); }
169 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_GETMAP(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GETMAP
); }
170 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_WAIT(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_WAIT
); }
171 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_MAP_BEGIN(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_MAP_BEGIN
); }
172 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_MAP_SIZE(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_MAP_SIZE
); }
173 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_MAP_DATA(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_MAP_DATA
); }
174 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_MAP_DONE
); }
175 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_MAP_OK(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_MAP_OK
); }
176 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_JOIN(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_JOIN
); }
177 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_FRAME(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_FRAME
); }
178 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_SYNC(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_SYNC
); }
179 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_ACK(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_ACK
); }
180 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMMAND
); }
181 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_COMMAND(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMMAND
); }
182 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_CHAT(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_CHAT
); }
183 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_CHAT(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_CHAT
); }
184 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_SET_PASSWORD(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_SET_PASSWORD
); }
185 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_SET_NAME
); }
186 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_QUIT
); }
187 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_ERROR
); }
188 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_QUIT(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_QUIT
); }
189 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_ERROR_QUIT(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_ERROR_QUIT
); }
190 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_SHUTDOWN(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_SHUTDOWN
); }
191 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_NEWGAME(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_NEWGAME
); }
192 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_RCON(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_RCON
); }
193 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_RCON(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_RCON
); }
194 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_CHECK_NEWGRFS
); }
195 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_NEWGRFS_CHECKED(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_NEWGRFS_CHECKED
); }
196 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_MOVE(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_MOVE
); }
197 NetworkRecvStatus
NetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_CLIENT_MOVE
); }
198 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_COMPANY_UPDATE(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMPANY_UPDATE
); }
199 NetworkRecvStatus
NetworkGameSocketHandler::Receive_SERVER_CONFIG_UPDATE(Packet
*p
) { return this->ReceiveInvalidPacket(PACKET_SERVER_CONFIG_UPDATE
); }
201 #endif /* ENABLE_NETWORK */