File diff r715:f920f6262d41 → r716:ae3edbaa50e7
network_server.c
Show inline comments
 
@@ -12,24 +12,26 @@
 
#include "vehicle.h"
 
#include "station.h"
 
#include "settings.h"
 

	
 
// This file handles all the server-commands
 

	
 
void NetworkHandleCommandQueue(ClientState *cs);
 
void NetworkHandleCommandQueue(NetworkClientState *cs);
 
void NetworkPopulateCompanyInfo(void);
 
void NetworkSendPatchSettings(ClientState *cs);
 
void NetworkSendPatchSettings(NetworkClientState *cs);
 

	
 
extern const char _openttd_revision[];
 

	
 
// Is the network enabled?
 

	
 
// **********
 
// Sending functions
 
//   DEF_SERVER_SEND_COMMAND has parameter: ClientState *cs
 
//   DEF_SERVER_SEND_COMMAND has parameter: NetworkClientState *cs
 
// **********
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CLIENT_INFO)(ClientState *cs, NetworkClientInfo *ci)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CLIENT_INFO)(NetworkClientState *cs, NetworkClientInfo *ci)
 
{
 
	//
 
	// Packet: SERVER_CLIENT_INFO
 
	// Function: Sends info about a client
 
	// Data:
 
	//    uint16:  The index of the client (always unique on a server. 1 = server)
 
@@ -116,22 +118,22 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_CO
 
			NetworkSend_string(p, _network_player_info[player->index].players);
 

	
 
		NetworkSend_Packet(p, cs);
 
	}
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(ClientState *cs, NetworkErrorCode error)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, NetworkErrorCode error)
 
{
 
	//
 
	// Packet: SERVER_ERROR
 
	// Function: The client made an error
 
	// Data:
 
	//    uint8:  ErrorID (see network_data.h, NetworkErrorCode)
 
	//
 

	
 
	ClientState *new_cs;
 
	NetworkClientState *new_cs;
 
	char str1[100], str2[100];
 
	char client_name[NETWORK_NAME_LENGTH];
 

	
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR);
 
	NetworkSend_uint8(p, error);
 
	NetworkSend_Packet(p, cs);
 
@@ -164,16 +166,16 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
	cs->quited = true;
 

	
 
	// Make sure the data get's there before we close the connection
 
	NetworkSend_Packets(cs);
 

	
 
	// The client made a mistake, so drop his connection now!
 
	CloseClient(cs);
 
	NetworkCloseClient(cs);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(ClientState *cs, NetworkPasswordType type)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkClientState *cs, NetworkPasswordType type)
 
{
 
	//
 
	// Packet: SERVER_NEED_PASSWORD
 
	// Function: Indication to the client that the server needs a password
 
	// Data:
 
	//    uint8:  Type of password
 
@@ -191,13 +193,13 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WE
 
	// Function: The client is joined and ready to receive his map
 
	// Data:
 
	//    uint16:  Own ClientID
 
	//
 

	
 
	Packet *p;
 
	ClientState *new_cs;
 
	NetworkClientState *new_cs;
 

	
 
	// Invalid packet when status is AUTH or higher
 
	if (cs->status >= STATUS_AUTH)
 
		return;
 

	
 
	cs->status = STATUS_AUTH;
 
@@ -223,13 +225,13 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WA
 
	// Function: The client can not receive the map at the moment because
 
	//             someone else is already receiving the map
 
	// Data:
 
	//    uint8:  Clients awaiting map
 
	//
 
	int waiting = 0;
 
	ClientState *new_cs;
 
	NetworkClientState *new_cs;
 
	Packet *p;
 

	
 
	// Count how many players are waiting in the queue
 
	FOR_ALL_CLIENTS(new_cs) {
 
		if (new_cs->status == STATUS_MAP_WAIT)
 
			waiting++;
 
@@ -324,13 +326,13 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MA
 
				// Set the status to DONE_MAP, no we will wait for the client
 
				//  to send it is ready (maybe that happens like never ;))
 
				cs->status = STATUS_DONE_MAP;
 
				fclose(file_pointer);
 

	
 
				{
 
					ClientState *new_cs;
 
					NetworkClientState *new_cs;
 
					bool new_map_client = false;
 
					// Check if there is a client waiting for receiving the map
 
					//  and start sending him the map
 
					FOR_ALL_CLIENTS(new_cs) {
 
						if (new_cs->status == STATUS_MAP_WAIT) {
 
							// Check if we already have a new client to send the map to
 
@@ -361,13 +363,13 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MA
 
			// Not everything is sent, decrease the sent_packets
 
			if (sent_packets > 1) sent_packets /= 2;
 
		}
 
	}
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_JOIN)(ClientState *cs, uint16 client_index)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_JOIN)(NetworkClientState *cs, uint16 client_index)
 
{
 
	//
 
	// Packet: SERVER_JOIN
 
	// Function: A client is joined (all active clients receive this after a
 
	//     PACKET_CLIENT_MAP_OK) Mostly what directly follows is a
 
	//     PACKET_SERVER_CLIENT_INFO
 
@@ -427,13 +429,13 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SY
 
#ifdef NETWORK_SEND_DOUBLE_SEED
 
	NetworkSend_uint32(p, _sync_seed_2);
 
#endif
 
	NetworkSend_Packet(p, cs);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_COMMAND)(ClientState *cs, CommandPacket *cp)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_COMMAND)(NetworkClientState *cs, CommandPacket *cp)
 
{
 
	//
 
	// Packet: SERVER_COMMAND
 
	// Function: Sends a DoCommand to the client
 
	// Data:
 
	//    uint8:  PlayerID (0..MAX_PLAYERS-1)
 
@@ -467,13 +469,13 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
	NetworkSend_uint8(p, cp->callback);
 
	NetworkSend_uint32(p, cp->frame);
 

	
 
	NetworkSend_Packet(p, cs);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(ClientState *cs, NetworkAction action, uint16 client_index, const char *msg)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkClientState *cs, NetworkAction action, uint16 client_index, const char *msg)
 
{
 
	//
 
	// Packet: SERVER_CHAT
 
	// Function: Sends a chat-packet to the client
 
	// Data:
 
	//    uint8:  ActionID (see network_data.h, NetworkAction)
 
@@ -487,13 +489,13 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
	NetworkSend_uint16(p, client_index);
 
	NetworkSend_string(p, msg);
 

	
 
	NetworkSend_Packet(p, cs);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(ClientState *cs, uint16 client_index, NetworkErrorCode errorno)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkClientState *cs, uint16 client_index, NetworkErrorCode errorno)
 
{
 
	//
 
	// Packet: SERVER_ERROR_QUIT
 
	// Function: One of the clients made an error and is quiting the game
 
	//      This packet informs the other clients of that.
 
	// Data:
 
@@ -506,13 +508,13 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
	NetworkSend_uint16(p, client_index);
 
	NetworkSend_uint8(p, errorno);
 

	
 
	NetworkSend_Packet(p, cs);
 
}
 

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_QUIT)(ClientState *cs, uint16 client_index, const char *leavemsg)
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_QUIT)(NetworkClientState *cs, uint16 client_index, const char *leavemsg)
 
{
 
	//
 
	// Packet: SERVER_ERROR_QUIT
 
	// Function: A client left the game, and this packets informs the other clients
 
	//      of that.
 
	// Data:
 
@@ -553,22 +555,20 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NE
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_NEWGAME);
 
	NetworkSend_Packet(p, cs);
 
}
 

	
 
// **********
 
// Receiving functions
 
//   DEF_SERVER_RECEIVE_COMMAND has parameter: ClientState *cs, Packet *p
 
//   DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientState *cs, Packet *p
 
// **********
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO)
 
{
 
	SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(cs);
 
}
 

	
 
extern const char _openttd_revision[];
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
 
{
 
	char name[NETWORK_NAME_LENGTH];
 
	char unique_id[NETWORK_NAME_LENGTH];
 
	NetworkClientInfo *ci;
 
	char test_name[NETWORK_NAME_LENGTH];
 
@@ -679,13 +679,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
	SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 
	return;
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
 
{
 
	ClientState *new_cs;
 
	NetworkClientState *new_cs;
 

	
 
	// The client was never joined.. so this is impossible, right?
 
	//  Ignore the packet, give the client a warning, and close his connection
 
	if (cs->status < STATUS_AUTH || cs->quited) {
 
		SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
 
		return;
 
@@ -708,13 +708,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
 
{
 
	// Client has the map, now start syncing
 
	if (cs->status == STATUS_DONE_MAP && !cs->quited) {
 
		char client_name[NETWORK_NAME_LENGTH];
 
		char str[100];
 
		ClientState *new_cs;
 
		NetworkClientState *new_cs;
 
		GetString(str, STR_NETWORK_CLIENT_JOINED);
 

	
 
		NetworkGetClientName(client_name, sizeof(client_name), cs);
 

	
 
		NetworkTextMessage(NETWORK_ACTION_JOIN_LEAVE, 1, client_name, str);
 

	
 
@@ -744,13 +744,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
 
{
 
	// The client has done a command and wants us to handle it
 
	int i;
 
	byte callback;
 
	ClientState *new_cs;
 
	NetworkClientState *new_cs;
 
	NetworkClientInfo *ci;
 
	char *dparam_char;
 

	
 
	CommandPacket *cp = malloc(sizeof(CommandPacket));
 

	
 
	// The client was never joined.. so this is impossible, right?
 
@@ -829,13 +829,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
 
{
 
	// This packets means a client noticed an error and is reporting this
 
	//  to us. Display the error and report it to the other clients
 
	ClientState *new_cs;
 
	NetworkClientState *new_cs;
 
	byte errorno = NetworkRecv_uint8(p);
 
	char str1[100], str2[100];
 
	char client_name[NETWORK_NAME_LENGTH];
 

	
 
	// The client was never joined.. thank the client for the packet, but ignore it
 
	if (cs->status < STATUS_DONE_MAP || cs->quited) {
 
@@ -862,13 +862,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
 
{
 
	// The client wants to leave. Display this and report it to the other
 
	//  clients.
 
	ClientState *new_cs;
 
	NetworkClientState *new_cs;
 
	char str1[100], str2[100];
 
	char client_name[NETWORK_NAME_LENGTH];
 

	
 
	// The client was never joined.. thank the client for the packet, but ignore it
 
	if (cs->status < STATUS_DONE_MAP || cs->quited) {
 
		cs->quited = true;
 
@@ -905,13 +905,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
}
 

	
 

	
 

	
 
void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, byte from_index)
 
{
 
	ClientState *cs;
 
	NetworkClientState *cs;
 
	NetworkClientInfo *ci, *ci_own, *ci_to;
 

	
 
	switch (desttype) {
 
	case DESTTYPE_CLIENT:
 
		if (dest == 1) {
 
			ci = NetworkFindClientInfoFromIndex(from_index);
 
@@ -1033,13 +1033,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
			NetworkUpdateClientInfo(ci->client_index);
 
		}
 
	}
 
}
 

	
 
// The layout for the receive-functions by the server
 
typedef void NetworkServerPacket(ClientState *cs, Packet *p);
 
typedef void NetworkServerPacket(NetworkClientState *cs, Packet *p);
 

	
 

	
 
// This array matches PacketType. At an incoming
 
//  packet it is matches against this array
 
//  and that way the right function to handle that
 
//  packet is found.
 
@@ -1081,13 +1081,13 @@ assert_compile(lengthof(_network_server_
 

	
 
extern const SettingDesc patch_settings[];
 

	
 
// This is a TEMPORARY solution to get the patch-settings
 
//  to the client. When the patch-settings are saved in the savegame
 
//  this should be removed!!
 
void NetworkSendPatchSettings(ClientState *cs)
 
void NetworkSendPatchSettings(NetworkClientState *cs)
 
{
 
	const SettingDesc *item;
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
 
	NetworkSend_uint8(p, MAP_PACKET_PATCH);
 
	// Now send all the patch-settings in a pretty order..
 

	
 
@@ -1119,13 +1119,13 @@ void NetworkSendPatchSettings(ClientStat
 
void NetworkPopulateCompanyInfo(void)
 
{
 
	char password[NETWORK_PASSWORD_LENGTH];
 
	Player *p;
 
	Vehicle *v;
 
	Station *s;
 
	ClientState *cs;
 
	NetworkClientState *cs;
 
	NetworkClientInfo *ci;
 
	int i;
 
	uint16 months_empty;
 

	
 
	FOR_ALL_PLAYERS(p) {
 
		if (!p->is_active) {
 
@@ -1219,13 +1219,13 @@ void NetworkPopulateCompanyInfo(void)
 
	}
 
}
 

	
 
// Send a packet to all clients with updated info about this client_index
 
void NetworkUpdateClientInfo(uint16 client_index)
 
{
 
	ClientState *cs;
 
	NetworkClientState *cs;
 
	NetworkClientInfo *ci;
 

	
 
	ci = NetworkFindClientInfoFromIndex(client_index);
 

	
 
	if (ci == NULL)
 
		return;
 
@@ -1239,13 +1239,13 @@ void NetworkUpdateClientInfo(uint16 clie
 
    Two things happen:
 
      1) If a company is not protected, it is closed after 1 year (for example)
 
      2) If a company is protected, protection is disabled after 3 years (for example)
 
           (and item 1. happens a year later) */
 
static void NetworkAutoCleanCompanies()
 
{
 
	ClientState *cs;
 
	NetworkClientState *cs;
 
	NetworkClientInfo *ci;
 
	Player *p;
 
	bool clients_in_company[MAX_PLAYERS];
 

	
 
	if (!_network_autoclean_companies)
 
		return;
 
@@ -1297,13 +1297,13 @@ static void NetworkAutoCleanCompanies()
 
}
 

	
 
// This function changes new_name to a name that is unique (by adding #1 ...)
 
//  and it returns true if that succeeded.
 
bool NetworkFindName(char new_name[NETWORK_NAME_LENGTH])
 
{
 
	ClientState *new_cs;
 
	NetworkClientState *new_cs;
 
	NetworkClientInfo *ci;
 
	bool found_name = false;
 
	byte number = 0;
 
	char original_name[NETWORK_NAME_LENGTH];
 

	
 
	// We use NETWORK_NAME_LENGTH in here, because new_name is really a pointer
 
@@ -1338,13 +1338,13 @@ bool NetworkFindName(char new_name[NETWO
 
	}
 

	
 
	return found_name;
 
}
 

	
 
// Reads a packet from the stream
 
bool NetworkServer_ReadPackets(ClientState *cs)
 
bool NetworkServer_ReadPackets(NetworkClientState *cs)
 
{
 
	Packet *p;
 
	NetworkRecvStatus res;
 
	while((p = NetworkRecv_Packet(cs, &res)) != NULL) {
 
		byte type = NetworkRecv_uint8(p);
 
		if (type < PACKET_END && _network_server_packet[type] != NULL)
 
@@ -1355,13 +1355,13 @@ bool NetworkServer_ReadPackets(ClientSta
 
	}
 

	
 
	return true;
 
}
 

	
 
// Handle the local command-queue
 
void NetworkHandleCommandQueue(ClientState *cs) {
 
void NetworkHandleCommandQueue(NetworkClientState *cs) {
 
	if (cs->command_queue != NULL) {
 
		CommandPacket *cp;
 
		CommandPacket *cp_prev;
 

	
 
		cp = cs->command_queue;
 
		cp_prev = NULL;
 
@@ -1386,13 +1386,13 @@ void NetworkHandleCommandQueue(ClientSta
 
// This is called every tick if this is a _network_server
 
void NetworkServer_Tick(void)
 
{
 
#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
 
	static uint32 last_sync_frame = 0;
 
#endif
 
	ClientState *cs;
 
	NetworkClientState *cs;
 
	bool send_frame = false;
 

	
 
	// Update max-frame-counter
 
	if (_frame_counter > _frame_counter_max) {
 
		_frame_counter_max = _frame_counter + _network_frame_freq;
 
		send_frame = true;
 
@@ -1407,13 +1407,13 @@ void NetworkServer_Tick(void)
 
			int lag = NetworkCalculateLag(cs) / DAY_TICKS;
 
			if (lag > 0) {
 
				if (lag > 3) {
 
					// Client did still not report in after 4 game-day, drop him
 
					//  (that is, the 3 of above, + 1 before any lag is counted)
 
					IConsolePrintF(_iconsole_color_error,"Client #%d is dropped because the client did not respond for more then 4 game-days", cs->index);
 
					CloseClient(cs);
 
					NetworkCloseClient(cs);
 
					continue;
 
				}
 

	
 
				// Report once per time we detect the lag
 
				if (cs->lag_test == 0) {
 
					IConsolePrintF(_iconsole_color_warning,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index);
 
@@ -1450,12 +1450,12 @@ void NetworkServer_Tick(void)
 
#endif
 

	
 
	/* See if we need to advertise */
 
	NetworkUDPAdvertise();
 
}
 

	
 
void NetworkServerMonthlyLoop()
 
void NetworkServerMonthlyLoop(void)
 
{
 
	NetworkAutoCleanCompanies();
 
}
 

	
 
#endif /* ENABLE_NETWORK */