Changeset - r14312:be27b5f00b31
[Not reviewed]
master
0 6 0
rubidium - 15 years ago 2010-01-21 11:17:40
rubidium@openttd.org
(svn r18875) -Codechange: remove some unneeded bits from the network protocol and improve the naming of some variables
6 files changed with 20 insertions and 27 deletions:
0 comments (0 inline, 0 general)
src/network/core/config.h
Show inline comments
 
@@ -15,51 +15,51 @@
 
#define NETWORK_CORE_CONFIG_H
 

	
 
/** DNS hostname of the masterserver */
 
#define NETWORK_MASTER_SERVER_HOST "master.openttd.org"
 
/** DNS hostname of the content server */
 
#define NETWORK_CONTENT_SERVER_HOST "content.openttd.org"
 
/** Message sent to the masterserver to 'identify' this client as OpenTTD */
 
#define NETWORK_MASTER_SERVER_WELCOME_MESSAGE "OpenTTDRegister"
 

	
 
enum {
 
	NETWORK_MASTER_SERVER_PORT    = 3978, ///< The default port of the master server (UDP)
 
	NETWORK_CONTENT_SERVER_PORT   = 3978, ///< The default port of the content server (TCP)
 
	NETWORK_DEFAULT_PORT          = 3979, ///< The default port of the game server (TCP & UDP)
 
	NETWORK_DEFAULT_DEBUGLOG_PORT = 3982, ///< The default port debug-log is sent too (TCP)
 

	
 
	SEND_MTU                      = 1460, ///< Number of bytes we can pack in a single packet
 

	
 
	NETWORK_GAME_INFO_VERSION     =    4, ///< What version of game-info do we use?
 
	NETWORK_COMPANY_INFO_VERSION  =    6, ///< What version of company info is this?
 
	NETWORK_MASTER_SERVER_VERSION =    2, ///< What version of master-server-protocol do we use?
 

	
 
	NETWORK_NAME_LENGTH           =   80, ///< The maximum length of the server name and map name, in bytes including '\0'
 
	NETWORK_COMPANY_NAME_LENGTH   =   31, ///< The maximum length of the company name, in bytes including '\0'
 
	NETWORK_HOSTNAME_LENGTH       =   80, ///< The maximum length of the host name, in bytes including '\0'
 
	NETWORK_UNIQUE_ID_LENGTH      =   33, ///< The maximum length of the unique id of the clients, in bytes including '\0'
 
	NETWORK_SERVER_ID_LENGTH      =   33, ///< The maximum length of the network id of the servers, in bytes including '\0'
 
	NETWORK_REVISION_LENGTH       =   15, ///< The maximum length of the revision, in bytes including '\0'
 
	NETWORK_PASSWORD_LENGTH       =   33, ///< The maximum length of the password, in bytes including '\0' (must be >= NETWORK_UNIQUE_ID_LENGTH)
 
	NETWORK_PASSWORD_LENGTH       =   33, ///< The maximum length of the password, in bytes including '\0' (must be >= NETWORK_SERVER_ID_LENGTH)
 
	NETWORK_CLIENTS_LENGTH        =  200, ///< The maximum length for the list of clients that controls a company, in bytes including '\0'
 
	NETWORK_CLIENT_NAME_LENGTH    =   25, ///< The maximum length of a client's name, in bytes including '\0'
 
	NETWORK_RCONCOMMAND_LENGTH    =  500, ///< The maximum length of a rconsole command, in bytes including '\0'
 
	NETWORK_CHAT_LENGTH           =  900, ///< The maximum length of a chat message, in bytes including '\0'
 

	
 
	NETWORK_GRF_NAME_LENGTH       =   80, ///< Maximum length of the name of a GRF
 
	/**
 
	 * Maximum number of GRFs that can be sent.
 
	 * This value is related to number of handles (files) OpenTTD can open.
 
	 * This is currently 64. Two are used for configuration and sound.
 
	 */
 
	NETWORK_MAX_GRF_COUNT         =   62,
 

	
 
	NETWORK_NUM_LANGUAGES         =   36, ///< Number of known languages (to the network protocol) + 1 for 'any'.
 
	/**
 
	 * The number of landscapes in OpenTTD.
 
	 * This number must be equal to NUM_LANDSCAPE, but as this number is used
 
	 * within the network code and that the network code is shared with the
 
	 * masterserver/updater, it has to be declared in here too. In network.cpp
 
	 * there is a compile assertion to check that this NUM_LANDSCAPE is equal
 
	 * to NETWORK_NUM_LANDSCAPES.
 
	 */
 
	NETWORK_NUM_LANDSCAPES        =    4,
 
};
src/network/network.cpp
Show inline comments
 
@@ -830,49 +830,48 @@ void NetworkClientConnectGame(NetworkAdd
 
	_network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
 
	ShowJoinStatusWindow();
 

	
 
	new TCPClientConnecter(address);
 
}
 

	
 
static void NetworkInitGameInfo()
 
{
 
	if (StrEmpty(_settings_client.network.server_name)) {
 
		snprintf(_settings_client.network.server_name, sizeof(_settings_client.network.server_name), "Unnamed Server");
 
	}
 

	
 
	/* The server is a client too */
 
	_network_game_info.clients_on = _network_dedicated ? 0 : 1;
 

	
 
	NetworkClientInfo *ci = new NetworkClientInfo(CLIENT_ID_SERVER);
 
	ci->client_playas = _network_dedicated ? COMPANY_SPECTATOR : _local_company;
 
	/* Give the server a valid IP; banning it is pointless anyways */
 
	sockaddr_in sock;
 
	memset(&sock, 0, sizeof(sock));
 
	sock.sin_family = AF_INET;
 
	ci->client_address = NetworkAddress((sockaddr*)&sock, sizeof(sock));
 

	
 
	strecpy(ci->client_name, _settings_client.network.client_name, lastof(ci->client_name));
 
	strecpy(ci->unique_id, _settings_client.network.network_id, lastof(ci->unique_id));
 
}
 

	
 
bool NetworkServerStart()
 
{
 
	if (!_network_available) return false;
 

	
 
	/* Call the pre-scripts */
 
	IConsoleCmdExec("exec scripts/pre_server.scr 0");
 
	if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0");
 

	
 
	NetworkDisconnect();
 
	NetworkInitialize();
 
	if (!NetworkListen()) return false;
 

	
 
	/* Try to start UDP-server */
 
	_network_udp_server = _udp_server_socket->Listen();
 

	
 
	_network_company_states = CallocT<NetworkCompanyState>(MAX_COMPANIES);
 
	_network_server = true;
 
	_networking = true;
 
	_frame_counter = 0;
 
	_frame_counter_server = 0;
 
	_frame_counter_max = 0;
 
	_last_sync_frame = 0;
 
@@ -1125,101 +1124,101 @@ void NetworkGameLoop()
 

	
 
		_sync_seed_1 = _random.state[0];
 
#ifdef NETWORK_SEND_DOUBLE_SEED
 
		_sync_seed_2 = _random.state[1];
 
#endif
 

	
 
		NetworkServer_Tick(send_frame);
 
	} else {
 
		/* Client */
 

	
 
		/* Make sure we are at the frame were the server is (quick-frames) */
 
		if (_frame_counter_server > _frame_counter) {
 
			while (_frame_counter_server > _frame_counter) {
 
				if (!NetworkDoClientLoop()) break;
 
			}
 
		} else {
 
			/* Else, keep on going till _frame_counter_max */
 
			if (_frame_counter_max > _frame_counter) NetworkDoClientLoop();
 
		}
 
	}
 

	
 
	NetworkSend();
 
}
 

	
 
static void NetworkGenerateUniqueId()
 
static void NetworkGenerateServerId()
 
{
 
	Md5 checksum;
 
	uint8 digest[16];
 
	char hex_output[16 * 2 + 1];
 
	char coding_string[NETWORK_NAME_LENGTH];
 
	int di;
 

	
 
	snprintf(coding_string, sizeof(coding_string), "%d%s", (uint)Random(), "OpenTTD Unique ID");
 
	snprintf(coding_string, sizeof(coding_string), "%d%s", (uint)Random(), "OpenTTD Server ID");
 

	
 
	/* Generate the MD5 hash */
 
	checksum.Append((const uint8*)coding_string, strlen(coding_string));
 
	checksum.Finish(digest);
 

	
 
	for (di = 0; di < 16; ++di) {
 
		sprintf(hex_output + di * 2, "%02x", digest[di]);
 
	}
 

	
 
	/* _network_unique_id is our id */
 
	/* _settings_client.network.network_id is our id */
 
	snprintf(_settings_client.network.network_id, sizeof(_settings_client.network.network_id), "%s", hex_output);
 
}
 

	
 
void NetworkStartDebugLog(NetworkAddress address)
 
{
 
	extern SOCKET _debug_socket;  // Comes from debug.c
 

	
 
	DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", address.GetHostname(), address.GetPort());
 

	
 
	SOCKET s = address.Connect();
 
	if (s == INVALID_SOCKET) {
 
		DEBUG(net, 0, "Failed to open socket for redirection DEBUG()");
 
		return;
 
	}
 

	
 
	_debug_socket = s;
 

	
 
	DEBUG(net, 0, "DEBUG() is now redirected");
 
}
 

	
 
/** This tries to launch the network for a given OS */
 
void NetworkStartUp()
 
{
 
	DEBUG(net, 3, "[core] starting network...");
 

	
 
	/* Network is available */
 
	_network_available = NetworkCoreInitialize();;
 
	_network_dedicated = false;
 
	_network_last_advertise_frame = 0;
 
	_network_need_advertise = true;
 
	_network_advertise_retries = 0;
 

	
 
	/* Generate an unique id when there is none yet */
 
	if (StrEmpty(_settings_client.network.network_id)) NetworkGenerateUniqueId();
 
	/* Generate an server id when there is none yet */
 
	if (StrEmpty(_settings_client.network.network_id)) NetworkGenerateServerId();
 

	
 
	memset(&_network_game_info, 0, sizeof(_network_game_info));
 

	
 
	NetworkInitialize();
 
	DEBUG(net, 3, "[core] network online, multiplayer available");
 
	NetworkFindBroadcastIPs(&_broadcast_list);
 
}
 

	
 
/** This shuts the network down */
 
void NetworkShutDown()
 
{
 
	NetworkDisconnect(true);
 
	NetworkUDPClose();
 

	
 
	DEBUG(net, 3, "[core] shutting down network");
 

	
 
	_network_available = false;
 

	
 
	NetworkCoreShutdown();
 
}
 

	
 
/**
 
 * Checks whether the given version string is compatible with our version.
 
 * @param other the version string to compare to
src/network/network_base.h
Show inline comments
 
@@ -8,35 +8,34 @@
 
 */
 

	
 
/** @file network_base.h Base core network types and some helper functions to access them. */
 

	
 
#ifndef NETWORK_BASE_H
 
#define NETWORK_BASE_H
 

	
 
#ifdef ENABLE_NETWORK
 

	
 
#include "network_type.h"
 
#include "core/address.h"
 
#include "../core/pool_type.hpp"
 
#include "../company_type.h"
 

	
 
typedef Pool<NetworkClientInfo, ClientIndex, 8, MAX_CLIENT_SLOTS> NetworkClientInfoPool;
 
extern NetworkClientInfoPool _networkclientinfo_pool;
 

	
 
struct NetworkClientInfo : NetworkClientInfoPool::PoolItem<&_networkclientinfo_pool> {
 
	ClientID client_id;                             ///< Client identifier (same as ClientState->client_id)
 
	char client_name[NETWORK_CLIENT_NAME_LENGTH];   ///< Name of the client
 
	byte client_lang;                               ///< The language of the client
 
	CompanyID client_playas;                        ///< As which company is this client playing (CompanyID)
 
	NetworkAddress client_address;                  ///< IP-address of the client (so he can be banned)
 
	Date join_date;                                 ///< Gamedate the client has joined
 
	char unique_id[NETWORK_UNIQUE_ID_LENGTH];       ///< Every play sends an unique id so we can indentify him
 

	
 
	NetworkClientInfo(ClientID client_id = INVALID_CLIENT_ID) : client_id(client_id) {}
 
	~NetworkClientInfo();
 
};
 

	
 
#define FOR_ALL_CLIENT_INFOS_FROM(var, start) FOR_ALL_ITEMS_FROM(NetworkClientInfo, clientinfo_index, var, start)
 
#define FOR_ALL_CLIENT_INFOS(var) FOR_ALL_CLIENT_INFOS_FROM(var, 0)
 

	
 
#endif /* ENABLE_NETWORK */
 
#endif /* NETWORK_BASE_H */
src/network/network_client.cpp
Show inline comments
 
@@ -21,157 +21,155 @@
 
#include "../fileio_func.h"
 
#include "../3rdparty/md5/md5.h"
 
#include "../strings_func.h"
 
#include "../window_func.h"
 
#include "../company_func.h"
 
#include "../company_base.h"
 
#include "../company_gui.h"
 
#include "../rev.h"
 
#include "network.h"
 
#include "network_base.h"
 

	
 
#include "table/strings.h"
 

	
 
/* This file handles all the client-commands */
 

	
 

	
 
/* So we don't make too much typos ;) */
 
#define MY_CLIENT NetworkClientSocket::Get(0)
 

	
 
static uint32 last_ack_frame;
 

	
 
/** One bit of 'entropy' used to generate a salt for the company passwords. */
 
static uint32 _password_game_seed;
 
/** The other bit of 'entropy' used to generate a salt for the company passwords. */
 
static char _password_server_unique_id[NETWORK_UNIQUE_ID_LENGTH];
 
static char _password_server_id[NETWORK_SERVER_ID_LENGTH];
 

	
 
/** Maximum number of companies of the currently joined server. */
 
static uint8 _network_server_max_companies;
 
/** Maximum number of spectators of the currently joined server. */
 
static uint8 _network_server_max_spectators;
 

	
 
/** Who would we like to join as. */
 
CompanyID _network_join_as;
 

	
 
/** Login password from -p argument */
 
const char *_network_join_server_password = NULL;
 
/** Company password from -P argument */
 
const char *_network_join_company_password = NULL;
 

	
 
/** Make sure the unique ID length is the same as a md5 hash. */
 
assert_compile(NETWORK_UNIQUE_ID_LENGTH == 16 * 2 + 1);
 
/** Make sure the server ID length is the same as a md5 hash. */
 
assert_compile(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1);
 

	
 
/**
 
 * Generates a hashed password for the company name.
 
 * @param password the password to 'encrypt'.
 
 * @return the hashed password.
 
 */
 
static const char *GenerateCompanyPasswordHash(const char *password)
 
{
 
	if (StrEmpty(password)) return password;
 

	
 
	char salted_password[NETWORK_UNIQUE_ID_LENGTH];
 
	char salted_password[NETWORK_SERVER_ID_LENGTH];
 

	
 
	memset(salted_password, 0, sizeof(salted_password));
 
	snprintf(salted_password, sizeof(salted_password), "%s", password);
 
	/* Add the game seed and the server's unique ID as the salt. */
 
	for (uint i = 0; i < NETWORK_UNIQUE_ID_LENGTH - 1; i++) salted_password[i] ^= _password_server_unique_id[i] ^ (_password_game_seed >> i);
 
	/* Add the game seed and the server's ID as the salt. */
 
	for (uint i = 0; i < NETWORK_SERVER_ID_LENGTH - 1; i++) salted_password[i] ^= _password_server_id[i] ^ (_password_game_seed >> i);
 

	
 
	Md5 checksum;
 
	uint8 digest[16];
 
	static char hashed_password[NETWORK_UNIQUE_ID_LENGTH];
 
	static char hashed_password[NETWORK_SERVER_ID_LENGTH];
 

	
 
	/* Generate the MD5 hash */
 
	checksum.Append((const uint8*)salted_password, sizeof(salted_password) - 1);
 
	checksum.Finish(digest);
 

	
 
	for (int di = 0; di < 16; di++) sprintf(hashed_password + di * 2, "%02x", digest[di]);
 
	hashed_password[lengthof(hashed_password) - 1] = '\0';
 

	
 
	return hashed_password;
 
}
 

	
 
/**
 
 * Hash the current company password; used when the server 'company' sets his/her password.
 
 */
 
void HashCurrentCompanyPassword(const char *password)
 
{
 
	_password_game_seed = _settings_game.game_creation.generation_seed;
 
	strecpy(_password_server_unique_id, _settings_client.network.network_id, lastof(_password_server_unique_id));
 
	strecpy(_password_server_id, _settings_client.network.network_id, lastof(_password_server_id));
 

	
 
	const char *new_pw = GenerateCompanyPasswordHash(password);
 
	strecpy(_network_company_states[_local_company].password, new_pw, lastof(_network_company_states[_local_company].password));
 

	
 
	if (_network_server) {
 
		NetworkServerUpdateCompanyPassworded(_local_company, !StrEmpty(_network_company_states[_local_company].password));
 
	}
 
}
 

	
 

	
 
/***********
 
 * Sending functions
 
 *   DEF_CLIENT_SEND_COMMAND has no parameters
 
 ************/
 

	
 
DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)
 
{
 
	/*
 
	 * Packet: CLIENT_COMPANY_INFO
 
	 * Function: Request company-info (in detail)
 
	 * Data:
 
	 *    <none>
 
	 */
 
	Packet *p;
 
	_network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
 
	SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0);
 

	
 
	p = new Packet(PACKET_CLIENT_COMPANY_INFO);
 
	MY_CLIENT->Send_Packet(p);
 
}
 

	
 
DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_JOIN)
 
{
 
	/*
 
	 * Packet: CLIENT_JOIN
 
	 * Function: Try to join the server
 
	 * Data:
 
	 *    String: OpenTTD Revision (norev000 if no revision)
 
	 *    String: Client Name (max NETWORK_NAME_LENGTH)
 
	 *    uint8:  Play as Company id (1..MAX_COMPANIES)
 
	 *    uint8:  Language ID
 
	 *    String: Unique id to find the client back in server-listing
 
	 */
 

	
 
	Packet *p;
 
	_network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
 
	SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0);
 

	
 
	p = new Packet(PACKET_CLIENT_JOIN);
 
	p->Send_string(_openttd_revision);
 
	p->Send_string(_settings_client.network.client_name); // Client name
 
	p->Send_uint8 (_network_join_as);     // PlayAs
 
	p->Send_uint8 (NETLANG_ANY);          // Language
 
	p->Send_string(_settings_client.network.network_id);
 
	MY_CLIENT->Send_Packet(p);
 
}
 

	
 
DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
 
{
 
	/*
 
	 * Packet: CLIENT_NEWGRFS_CHECKED
 
	 * Function: Tell the server that we have the required GRFs
 
	 * Data:
 
	 */
 

	
 
	Packet *p = new Packet(PACKET_CLIENT_NEWGRFS_CHECKED);
 
	MY_CLIENT->Send_Packet(p);
 
}
 

	
 
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password)
 
{
 
	/*
 
	 * Packet: CLIENT_PASSWORD
 
	 * Function: Send a password to the server to authorize
 
	 * Data:
 
	 *    uint8:  NetworkPasswordType
 
	 *    String: Password
 
	 */
 
@@ -511,71 +509,71 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
			ret = NETWORK_RECV_STATUS_NEWGRF_MISMATCH;
 
		}
 
	}
 

	
 
	if (ret == NETWORK_RECV_STATUS_OKAY) {
 
		/* Start receiving the map */
 
		SEND_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)();
 
	} else {
 
		/* NewGRF mismatch, bail out */
 
		_switch_mode_errorstr = STR_NETWORK_ERROR_NEWGRF_MISMATCH;
 
	}
 
	return ret;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD)
 
{
 
	NetworkPasswordType type = (NetworkPasswordType)p->Recv_uint8();
 

	
 
	const char *password = _network_join_server_password;
 

	
 
	switch (type) {
 
		case NETWORK_COMPANY_PASSWORD:
 
			/* Initialize the password hash salting variables. */
 
			_password_game_seed = p->Recv_uint32();
 
			p->Recv_string(_password_server_unique_id, sizeof(_password_server_unique_id));
 
			p->Recv_string(_password_server_id, sizeof(_password_server_id));
 
			if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 
			password = _network_join_company_password;
 
			/* FALL THROUGH */
 
		case NETWORK_GAME_PASSWORD:
 
			if (StrEmpty(password)) {
 
				ShowNetworkNeedPassword(type);
 
			} else {
 
				SEND_COMMAND(PACKET_CLIENT_PASSWORD)(type, password);
 
			}
 
			return NETWORK_RECV_STATUS_OKAY;
 

	
 
		default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 
	}
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
 
{
 
	_network_own_client_id = (ClientID)p->Recv_uint32();
 

	
 
	/* Initialize the password hash salting variables, even if they were previously. */
 
	_password_game_seed = p->Recv_uint32();
 
	p->Recv_string(_password_server_unique_id, sizeof(_password_server_unique_id));
 
	p->Recv_string(_password_server_id, sizeof(_password_server_id));
 

	
 
	/* Start receiving the map */
 
	SEND_COMMAND(PACKET_CLIENT_GETMAP)();
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WAIT)
 
{
 
	_network_join_status = NETWORK_JOIN_STATUS_WAITING;
 
	_network_join_waiting = p->Recv_uint8();
 
	SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0);
 

	
 
	/* We are put on hold for receiving the map.. we need GUI for this ;) */
 
	DEBUG(net, 1, "The server is currently busy sending the map to someone else, please wait..." );
 
	DEBUG(net, 1, "There are %d clients in front of you", _network_join_waiting);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
 
{
 
	static FILE *file_pointer;
 

	
 
	byte maptype;
src/network/network_server.cpp
Show inline comments
 
@@ -637,105 +637,102 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	NetworkClientInfo *ci = cs->GetInfo();
 

	
 
	/* We now want a password from the client else we do not allow him in! */
 
	if (!StrEmpty(_settings_client.network.server_password)) {
 
		SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD);
 
	} else {
 
		if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
 
			SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
 
		} else {
 
			SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
 
		}
 
	}
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
 
{
 
	if (cs->status != STATUS_INACTIVE) {
 
		/* Illegal call, return error and ignore the packet */
 
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 
		return NETWORK_RECV_STATUS_OKAY;
 
	}
 

	
 
	char name[NETWORK_CLIENT_NAME_LENGTH];
 
	char unique_id[NETWORK_UNIQUE_ID_LENGTH];
 
	NetworkClientInfo *ci;
 
	CompanyID playas;
 
	NetworkLanguage client_lang;
 
	char client_revision[NETWORK_REVISION_LENGTH];
 

	
 
	p->Recv_string(client_revision, sizeof(client_revision));
 

	
 
	/* Check if the client has revision control enabled */
 
	if (!IsNetworkCompatibleVersion(client_revision)) {
 
		/* Different revisions!! */
 
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_REVISION);
 
		return NETWORK_RECV_STATUS_OKAY;
 
	}
 

	
 
	p->Recv_string(name, sizeof(name));
 
	playas = (Owner)p->Recv_uint8();
 
	client_lang = (NetworkLanguage)p->Recv_uint8();
 
	p->Recv_string(unique_id, sizeof(unique_id));
 

	
 
	if (cs->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 

	
 
	/* join another company does not affect these values */
 
	switch (playas) {
 
		case COMPANY_NEW_COMPANY: // New company
 
			if (Company::GetNumItems() >= _settings_client.network.max_companies) {
 
				SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
 
				return NETWORK_RECV_STATUS_OKAY;
 
			}
 
			break;
 
		case COMPANY_SPECTATOR: // Spectator
 
			if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
 
				SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
 
				return NETWORK_RECV_STATUS_OKAY;
 
			}
 
			break;
 
		default: // Join another company (companies 1-8 (index 0-7))
 
			if (!Company::IsValidHumanID(playas)) {
 
				SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_COMPANY_MISMATCH);
 
				return NETWORK_RECV_STATUS_OKAY;
 
			}
 
			break;
 
	}
 

	
 
	/* We need a valid name.. make it Player */
 
	if (StrEmpty(name)) strecpy(name, "Player", lastof(name));
 

	
 
	if (!NetworkFindName(name)) { // Change name if duplicate
 
		/* We could not create a name for this client */
 
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NAME_IN_USE);
 
		return NETWORK_RECV_STATUS_OKAY;
 
	}
 

	
 
	ci = cs->GetInfo();
 

	
 
	strecpy(ci->client_name, name, lastof(ci->client_name));
 
	strecpy(ci->unique_id, unique_id, lastof(ci->unique_id));
 
	ci->client_playas = playas;
 
	ci->client_lang = client_lang;
 

	
 
	/* Make sure companies to which people try to join are not autocleaned */
 
	if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0;
 

	
 
	if (_grfconfig == NULL) {
 
		RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)(cs, NULL);
 
	} else {
 
		SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(cs);
 
	}
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
 
{
 
	NetworkPasswordType type;
 
	char password[NETWORK_PASSWORD_LENGTH];
 
	const NetworkClientInfo *ci;
 

	
 
	type = (NetworkPasswordType)p->Recv_uint8();
 
	p->Recv_string(password, sizeof(password));
 

	
 
	if (cs->status == STATUS_AUTHORIZING && type == NETWORK_GAME_PASSWORD) {
 
@@ -1712,52 +1709,52 @@ const char *GetClientIP(NetworkClientInf
 
{
 
	return ci->client_address.GetHostname();
 
}
 

	
 
void NetworkServerShowStatusToConsole()
 
{
 
	static const char * const stat_str[] = {
 
		"inactive",
 
		"authorizing",
 
		"authorized",
 
		"waiting",
 
		"loading map",
 
		"map done",
 
		"ready",
 
		"active"
 
	};
 

	
 
	NetworkClientSocket *cs;
 
	FOR_ALL_CLIENT_SOCKETS(cs) {
 
		int lag = NetworkCalculateLag(cs);
 
		NetworkClientInfo *ci = cs->GetInfo();
 
		const char *status;
 

	
 
		status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
 
		IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s  unique-id: '%s'",
 
		IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s",
 
			cs->client_id, ci->client_name, status, lag,
 
			ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
 
			GetClientIP(ci), ci->unique_id);
 
			GetClientIP(ci));
 
	}
 
}
 

	
 
/**
 
 * Send Config Update
 
 */
 
void NetworkServerSendConfigUpdate()
 
{
 
	NetworkClientSocket *cs;
 

	
 
	FOR_ALL_CLIENT_SOCKETS(cs) {
 
		SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)(cs);
 
	}
 
}
 

	
 
void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
 
{
 
	if (NetworkCompanyIsPassworded(company_id) == passworded) return;
 

	
 
	SB(_network_company_passworded, company_id, 1, !!passworded);
 
	SetWindowClassesDirty(WC_COMPANY);
 

	
 
	NetworkClientSocket *cs;
 
	FOR_ALL_CLIENT_SOCKETS(cs) {
src/settings_type.h
Show inline comments
 
@@ -112,49 +112,49 @@ struct GUISettings {
 
struct LocaleSettings {
 
	byte   currency;                         ///< currency we currently use
 
	byte   units;                            ///< unit system we show everything
 
	char  *digit_group_separator;            ///< thousand separator for non-currencies
 
	char  *digit_group_separator_currency;   ///< thousand separator for currencies
 
	char  *digit_decimal_separator;          ///< decimal separator
 
};
 

	
 
/** All settings related to the network. */
 
struct NetworkSettings {
 
#ifdef ENABLE_NETWORK
 
	uint16 sync_freq;                                     ///< how often do we check whether we are still in-sync
 
	uint8  frame_freq;                                    ///< how often do we send commands to the clients
 
	uint16 max_join_time;                                 ///< maximum amount of time, in game ticks, a client may take to join
 
	bool   pause_on_join;                                 ///< pause the game when people join
 
	uint16 server_port;                                   ///< port the server listens on
 
	char   server_name[NETWORK_NAME_LENGTH];              ///< name of the server
 
	char   server_password[NETWORK_PASSWORD_LENGTH];      ///< passowrd for joining this server
 
	char   rcon_password[NETWORK_PASSWORD_LENGTH];        ///< passowrd for rconsole (server side)
 
	bool   server_advertise;                              ///< advertise the server to the masterserver
 
	uint8  lan_internet;                                  ///< search on the LAN or internet for servers
 
	char   client_name[NETWORK_CLIENT_NAME_LENGTH];       ///< name of the player (as client)
 
	char   default_company_pass[NETWORK_PASSWORD_LENGTH]; ///< default password for new companies in encrypted form
 
	char   connect_to_ip[NETWORK_HOSTNAME_LENGTH];        ///< default for the "Add server" query
 
	char   network_id[NETWORK_UNIQUE_ID_LENGTH];          ///< semi-unique ID of the client
 
	char   network_id[NETWORK_SERVER_ID_LENGTH];          ///< network ID for servers
 
	bool   autoclean_companies;                           ///< automatically remove companies that are not in use
 
	uint8  autoclean_unprotected;                         ///< remove passwordless companies after this many months
 
	uint8  autoclean_protected;                           ///< remove the password from passworded companies after this many months
 
	uint8  autoclean_novehicles;                          ///< remove companies with no vehicles after this many months
 
	uint8  max_companies;                                 ///< maximum amount of companies
 
	uint8  max_clients;                                   ///< maximum amount of clients
 
	uint8  max_spectators;                                ///< maximum amount of spectators
 
	Year   restart_game_year;                             ///< year the server restarts
 
	uint8  min_active_clients;                            ///< minimum amount of active clients to unpause the game
 
	uint8  server_lang;                                   ///< language of the server
 
	bool   reload_cfg;                                    ///< reload the config file before restarting
 
	char   last_host[NETWORK_HOSTNAME_LENGTH];            ///< IP address of the last joined server
 
	uint16 last_port;                                     ///< port of the last joined server
 
#else /* ENABLE_NETWORK */
 
#endif
 
};
 

	
 
/** Settings related to the creation of games. */
 
struct GameCreationSettings {
 
	uint32 generation_seed;                  ///< noise seed for world generation
 
	Year   starting_year;                    ///< starting date
 
	uint8  map_x;                            ///< X size of map
 
	uint8  map_y;                            ///< Y size of map
 
	byte   land_generator;                   ///< the landscape generator
0 comments (0 inline, 0 general)