OpenTTD/src/network/network_admin.cpp

203 lines
5.6 KiB
C++
Raw Normal View History

/* $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 network_admin.cpp Server part of the admin network protocol. */
#ifdef ENABLE_NETWORK
#include "../stdafx.h"
#include "../debug.h"
#include "../strings_func.h"
#include "../date_func.h"
#include "network_admin.h"
#include "network.h"
#include "network_base.h"
#include "../company_base.h"
#include "../console_func.h"
#include "../core/pool_func.hpp"
#include "../map_func.h"
#include "../rev.h"
#include "table/strings.h"
/* This file handles all the admin network commands. */
/** The amount of admins connected. */
byte _network_admins_connected = 0;
NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
/**
* Create a new socket for the server side of the admin network.
* @param s The socket to connect with.
*/
ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : NetworkAdminSocketHandler(s)
{
_network_admins_connected++;
this->status = ADMIN_STATUS_INACTIVE;
}
/**
* Clear everything related to this admin.
*/
ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
{
_network_admins_connected--;
DEBUG(net, 1, "[admin] '%s' (%s) has disconnected", this->admin_name, this->admin_version);
}
/**
* Whether a connection is allowed or not at this moment.
* @return Whether the connection is allowed.
*/
/* static */ bool ServerNetworkAdminSocketHandler::AllowConnection()
{
return !StrEmpty(_settings_client.network.admin_password) && _network_admins_connected < MAX_ADMINS;
}
/** Send the packets for the server sockets. */
/* static */ void ServerNetworkAdminSocketHandler::Send()
{
ServerNetworkAdminSocketHandler *as;
FOR_ALL_ADMIN_SOCKETS(as) {
if (as->writable) {
as->Send_Packets();
}
}
}
/* static */ void ServerNetworkAdminSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address)
{
ServerNetworkAdminSocketHandler *as = new ServerNetworkAdminSocketHandler(s);
as->address = address; // Save the IP of the client
}
/***********
* Sending functions for admin network
************/
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error)
{
Packet *p = new Packet(ADMIN_PACKET_SERVER_ERROR);
p->Send_uint8(error);
this->Send_Packet(p);
char str[100];
StringID strid = GetNetworkErrorMsg(error);
GetString(str, strid, lastof(str));
DEBUG(net, 1, "[admin] the admin '%s' (%s) made an error and has been disconnected. Reason: '%s'", this->admin_name, this->admin_version, str);
return this->CloseConnection(true);
}
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol()
{
Packet *p = new Packet(ADMIN_PACKET_SERVER_PROTOCOL);
/* announce the protocol version */
p->Send_uint8(NETWORK_GAME_ADMIN_VERSION);
p->Send_bool(false);
this->Send_Packet(p);
return this->SendWelcome();
}
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome()
{
this->status = ADMIN_STATUS_ACTIVE;
Packet *p = new Packet(ADMIN_PACKET_SERVER_WELCOME);
p->Send_string(_settings_client.network.server_name);
p->Send_string(_openttd_revision);
p->Send_bool (_network_dedicated);
p->Send_string(_network_game_info.map_name);
p->Send_uint32(_settings_game.game_creation.generation_seed);
p->Send_uint8 (_settings_game.game_creation.landscape);
p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
p->Send_uint16(MapSizeX());
p->Send_uint16(MapSizeY());
this->Send_Packet(p);
return NETWORK_RECV_STATUS_OKAY;
}
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendNewGame()
{
Packet *p = new Packet(ADMIN_PACKET_SERVER_NEWGAME);
this->Send_Packet(p);
return NETWORK_RECV_STATUS_OKAY;
}
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendShutdown()
{
Packet *p = new Packet(ADMIN_PACKET_SERVER_SHUTDOWN);
this->Send_Packet(p);
return NETWORK_RECV_STATUS_OKAY;
}
/***********
* Receiving functions
************/
DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_JOIN)
{
if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
char password[NETWORK_PASSWORD_LENGTH];
p->Recv_string(password, sizeof(password));
if (StrEmpty(_settings_client.network.admin_password) ||
strcmp(password, _settings_client.network.admin_password) != 0) {
/* Password is invalid */
return this->SendError(NETWORK_ERROR_WRONG_PASSWORD);
}
p->Recv_string(this->admin_name, sizeof(this->admin_name));
p->Recv_string(this->admin_version, sizeof(this->admin_version));
if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) {
/* no name or version supplied */
return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
}
DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version);
return this->SendProtocol();
}
DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_QUIT)
{
/* The admin is leaving nothing else to do */
return this->CloseConnection();
}
/*
* Useful wrapper functions
*/
/**
* Send a Welcome packet to all connected admins
*/
void ServerNetworkAdminSocketHandler::WelcomeAll()
{
ServerNetworkAdminSocketHandler *as;
FOR_ALL_ADMIN_SOCKETS(as) {
as->SendWelcome();
}
}
#endif /* ENABLE_NETWORK */