mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-13 07:10:57 +00:00
211 lines
8.2 KiB
C++
211 lines
8.2 KiB
C++
/* $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.cpp Basic functions to receive and send TCP packets for game purposes.
|
|
*/
|
|
|
|
#ifdef ENABLE_NETWORK
|
|
|
|
#include "../../stdafx.h"
|
|
|
|
#include "../network.h"
|
|
#include "../network_internal.h"
|
|
#include "../../core/pool_func.hpp"
|
|
#include "../../debug.h"
|
|
|
|
#include "table/strings.h"
|
|
|
|
/** Make very sure the preconditions given in network_type.h are actually followed */
|
|
assert_compile(MAX_CLIENT_SLOTS > MAX_CLIENTS);
|
|
assert_compile(NetworkClientSocketPool::MAX_SIZE == MAX_CLIENT_SLOTS);
|
|
|
|
NetworkClientSocketPool _networkclientsocket_pool("NetworkClientSocket");
|
|
INSTANTIATE_POOL_METHODS(NetworkClientSocket)
|
|
|
|
/**
|
|
* Create a new socket for the game connection.
|
|
* @param s The socket to connect with.
|
|
*/
|
|
NetworkGameSocketHandler::NetworkGameSocketHandler(SOCKET s)
|
|
{
|
|
this->status = STATUS_INACTIVE;
|
|
this->sock = s;
|
|
this->last_frame = _frame_counter;
|
|
this->last_frame_server = _frame_counter;
|
|
}
|
|
|
|
/**
|
|
* 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 NetworkGameSocketHandler::CloseConnection(bool error)
|
|
{
|
|
/* 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_ERROR_LOSTCONNECTION;
|
|
|
|
return NETWORK_RECV_STATUS_CONN_LOST;
|
|
}
|
|
|
|
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 */
|