Changeset - r14988:e84b1f39bc47
[Not reviewed]
master
0 3 0
smatz - 14 years ago 2010-04-11 17:32:14
smatz@openttd.org
(svn r19610) -Codechange: rename STATUS_AUTH to STATUS_AUTHORIZED
3 files changed with 26 insertions and 26 deletions:
0 comments (0 inline, 0 general)
src/network/core/tcp_game.h
Show inline comments
 
@@ -55,57 +55,57 @@ enum {
 
	PACKET_CLIENT_SET_PASSWORD,
 
	PACKET_CLIENT_SET_NAME,
 
	PACKET_CLIENT_QUIT,
 
	PACKET_CLIENT_ERROR,
 
	PACKET_SERVER_QUIT,
 
	PACKET_SERVER_ERROR_QUIT,
 
	PACKET_SERVER_SHUTDOWN,
 
	PACKET_SERVER_NEWGAME,
 
	PACKET_SERVER_RCON,
 
	PACKET_CLIENT_RCON,
 
	PACKET_SERVER_CHECK_NEWGRFS,
 
	PACKET_CLIENT_NEWGRFS_CHECKED,
 
	PACKET_SERVER_MOVE,
 
	PACKET_CLIENT_MOVE,
 
	PACKET_SERVER_COMPANY_UPDATE,
 
	PACKET_SERVER_CONFIG_UPDATE,
 
	PACKET_END                   ///< Must ALWAYS be on the end of this list!! (period)
 
};
 

	
 
/** Packet that wraps a command */
 
struct CommandPacket;
 

	
 
/** Status of a client */
 
enum ClientStatus {
 
	STATUS_INACTIVE,   ///< The client is not connected nor active
 
	STATUS_AUTH_GAME,  ///< The client is authorizing with game (server) password
 
	STATUS_INACTIVE,     ///< The client is not connected nor active
 
	STATUS_AUTH_GAME,    ///< The client is authorizing with game (server) password
 
	STATUS_AUTH_COMPANY, ///< The client is authorizing with company password
 
	STATUS_AUTH,       ///< The client is authorized
 
	STATUS_MAP_WAIT,   ///< The client is waiting as someone else is downloading the map
 
	STATUS_MAP,        ///< The client is downloading the map
 
	STATUS_DONE_MAP,   ///< The client has downloaded the map
 
	STATUS_PRE_ACTIVE, ///< The client is catching up the delayed frames
 
	STATUS_ACTIVE,     ///< The client is active within in the game
 
	STATUS_AUTHORIZED,   ///< The client is authorized
 
	STATUS_MAP_WAIT,     ///< The client is waiting as someone else is downloading the map
 
	STATUS_MAP,          ///< The client is downloading the map
 
	STATUS_DONE_MAP,     ///< The client has downloaded the map
 
	STATUS_PRE_ACTIVE,   ///< The client is catching up the delayed frames
 
	STATUS_ACTIVE,       ///< The client is active within in the game
 
};
 

	
 
class NetworkClientSocket;
 
typedef Pool<NetworkClientSocket, ClientIndex, 8, MAX_CLIENT_SLOTS> NetworkClientSocketPool;
 
extern NetworkClientSocketPool _networkclientsocket_pool;
 

	
 
/** Base socket handler for all TCP sockets */
 
class NetworkClientSocket : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkTCPSocketHandler {
 
/* TODO: rewrite into a proper class */
 
private:
 
	NetworkClientInfo *info;  ///< Client info related to this socket
 
public:
 
	ClientID client_id;       ///< Client identifier
 
	uint32 last_frame;        ///< Last frame we have executed
 
	uint32 last_frame_server; ///< Last frame the server has executed
 
	byte lag_test;            ///< Byte used for lag-testing the client
 

	
 
	ClientStatus status;      ///< Status of this client
 

	
 
	CommandPacket *command_queue; ///< The command-queue awaiting delivery
 

	
 
	NetworkRecvStatus CloseConnection(bool error = true);
 

	
 
	NetworkClientSocket(ClientID client_id = INVALID_CLIENT_ID);
src/network/network.cpp
Show inline comments
 
@@ -431,49 +431,49 @@ static uint NetworkCountActiveClients()
 
	return count;
 
}
 

	
 
/**
 
 * Check if the minimum number of active clients has been reached and pause or unpause the game as appropriate
 
 */
 
static void CheckMinActiveClients()
 
{
 
	if ((_pause_mode & PM_PAUSED_ERROR) != PM_UNPAUSED ||
 
			!_network_dedicated ||
 
			(_settings_client.network.min_active_clients == 0 && (_pause_mode & PM_PAUSED_ACTIVE_CLIENTS) == PM_UNPAUSED)) {
 
		return;
 
	}
 
	CheckPauseHelper(NetworkCountActiveClients() < _settings_client.network.min_active_clients, PM_PAUSED_ACTIVE_CLIENTS);
 
}
 

	
 
/**
 
 * Checks whether there is a joining client
 
 * @return true iff one client is joining (but not authorizing)
 
 */
 
static bool NetworkHasJoiningClient()
 
{
 
	const NetworkClientSocket *cs;
 
	FOR_ALL_CLIENT_SOCKETS(cs) {
 
		if (cs->status >= STATUS_AUTH && cs->status < STATUS_ACTIVE) return true;
 
		if (cs->status >= STATUS_AUTHORIZED && cs->status < STATUS_ACTIVE) return true;
 
	}
 

	
 
	return false;
 
}
 

	
 
/**
 
 * Check whether we should pause on join
 
 */
 
static void CheckPauseOnJoin()
 
{
 
	if ((_pause_mode & PM_PAUSED_ERROR) != PM_UNPAUSED ||
 
			(!_settings_client.network.pause_on_join && (_pause_mode & PM_PAUSED_JOIN) == PM_UNPAUSED)) {
 
		return;
 
	}
 
	CheckPauseHelper(NetworkHasJoiningClient(), PM_PAUSED_JOIN);
 
}
 

	
 
/** Converts a string to ip/port/company
 
 *  Format: IP:port#company
 
 *
 
 * connection_string will be re-terminated to seperate out the hostname, and company and port will
 
 * be set to the company and port strings given by the user, inside the memory area originally
 
 * occupied by connection_string. */
 
void ParseConnectionString(const char **company, const char **port, char *connection_string)
 
@@ -527,70 +527,70 @@ static NetworkClientSocket *NetworkAlloc
 
		NetworkClientInfo *ci = new NetworkClientInfo(cs->client_id);
 
		cs->SetInfo(ci);
 
		ci->client_playas = COMPANY_INACTIVE_CLIENT;
 
		ci->join_date = _date;
 

	
 
		SetWindowDirty(WC_CLIENT_LIST, 0);
 
	}
 

	
 
	return cs;
 
}
 

	
 
/* Close a connection */
 
NetworkRecvStatus NetworkCloseClient(NetworkClientSocket *cs, NetworkRecvStatus status)
 
{
 
	assert(status != NETWORK_RECV_STATUS_OKAY);
 
	/*
 
	 * Sending a message just before leaving the game calls cs->Send_Packets.
 
	 * This might invoke this function, which means that when we close the
 
	 * connection after cs->Send_Packets we will close an already closed
 
	 * connection. This handles that case gracefully without having to make
 
	 * that code any more complex or more aware of the validity of the socket.
 
	 */
 
	if (cs->sock == INVALID_SOCKET) return status;
 

	
 
	if (status != NETWORK_RECV_STATUS_CONN_LOST && !cs->HasClientQuit() && _network_server && cs->status >= STATUS_AUTH) {
 
	if (status != NETWORK_RECV_STATUS_CONN_LOST && !cs->HasClientQuit() && _network_server && cs->status >= STATUS_AUTHORIZED) {
 
		/* We did not receive a leave message from this client... */
 
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 
		NetworkClientSocket *new_cs;
 

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

	
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
 

	
 
		/* Inform other clients of this... strange leaving ;) */
 
		FOR_ALL_CLIENT_SOCKETS(new_cs) {
 
			if (new_cs->status > STATUS_AUTH && cs != new_cs) {
 
			if (new_cs->status > STATUS_AUTHORIZED && cs != new_cs) {
 
				SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, NETWORK_ERROR_CONNECTION_LOST);
 
			}
 
		}
 
	}
 

	
 
	DEBUG(net, 1, "Closed client connection %d", cs->client_id);
 

	
 
	if (_network_server) {
 
		/* We just lost one client :( */
 
		if (cs->status >= STATUS_AUTH) _network_game_info.clients_on--;
 
		if (cs->status >= STATUS_AUTHORIZED) _network_game_info.clients_on--;
 
		_network_clients_connected--;
 

	
 
		SetWindowDirty(WC_CLIENT_LIST, 0);
 
	}
 

	
 
	cs->Send_Packets(true);
 

	
 
	delete cs->GetInfo();
 
	delete cs;
 

	
 
	return status;
 
}
 

	
 
/* For the server, to accept new clients */
 
static void NetworkAcceptClients(SOCKET ls)
 
{
 
	for (;;) {
 
		struct sockaddr_storage sin;
 
		memset(&sin, 0, sizeof(sin));
 
		socklen_t sin_len = sizeof(sin);
 
		SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
 
		if (s == INVALID_SOCKET) return;
 

	
 
		SetNonBlocking(s); // XXX error handling?
src/network/network_server.cpp
Show inline comments
 
@@ -131,60 +131,60 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_CO
 

	
 
	cs->Send_Packet(p);
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

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

	
 
	char str[100];
 
	Packet *p = new Packet(PACKET_SERVER_ERROR);
 

	
 
	p->Send_uint8(error);
 
	cs->Send_Packet(p);
 

	
 
	StringID strid = GetNetworkErrorMsg(error);
 
	GetString(str, strid, lastof(str));
 

	
 
	/* Only send when the current client was in game */
 
	if (cs->status > STATUS_AUTH) {
 
	if (cs->status > STATUS_AUTHORIZED) {
 
		NetworkClientSocket *new_cs;
 
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 

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

	
 
		DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
 

	
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
 

	
 
		FOR_ALL_CLIENT_SOCKETS(new_cs) {
 
			if (new_cs->status > STATUS_AUTH && new_cs != cs) {
 
			if (new_cs->status > STATUS_AUTHORIZED && new_cs != cs) {
 
				/* Some errors we filter to a more general error. Clients don't have to know the real
 
				 *  reason a joining failed. */
 
				if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION)
 
					error = NETWORK_ERROR_ILLEGAL_PACKET;
 

	
 
				SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, error);
 
			}
 
		}
 
	} else {
 
		DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", cs->client_id, str);
 
	}
 

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

	
 
DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHECK_NEWGRFS)(NetworkClientSocket *cs)
 
{
 
	/*
 
	 * Packet: PACKET_SERVER_CHECK_NEWGRFS
 
	 * Function: Sends info about the used GRFs to the client
 
	 * Data:
 
	 *      uint8:  Amount of GRFs
 
	 *    And then for each GRF:
 
@@ -240,62 +240,62 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
	if (cs->status >= STATUS_AUTH_COMPANY) return NetworkCloseClient(cs, NETWORK_RECV_STATUS_MALFORMED_PACKET);
 

	
 
	cs->status = STATUS_AUTH_COMPANY;
 

	
 
	Packet *p = new Packet(PACKET_SERVER_NEED_COMPANY_PASSWORD);
 
	p->Send_uint32(_settings_game.game_creation.generation_seed);
 
	p->Send_string(_settings_client.network.network_id);
 
	cs->Send_Packet(p);
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WELCOME)
 
{
 
	/*
 
	 * Packet: SERVER_WELCOME
 
	 * Function: The client is joined and ready to receive his map
 
	 * Data:
 
	 *    uint32:  Own Client identifier
 
	 */
 

	
 
	Packet *p;
 
	NetworkClientSocket *new_cs;
 

	
 
	/* Invalid packet when status is AUTH or higher */
 
	if (cs->status >= STATUS_AUTH) return NetworkCloseClient(cs, NETWORK_RECV_STATUS_MALFORMED_PACKET);
 
	if (cs->status >= STATUS_AUTHORIZED) return NetworkCloseClient(cs, NETWORK_RECV_STATUS_MALFORMED_PACKET);
 

	
 
	cs->status = STATUS_AUTH;
 
	cs->status = STATUS_AUTHORIZED;
 
	_network_game_info.clients_on++;
 

	
 
	p = new Packet(PACKET_SERVER_WELCOME);
 
	p->Send_uint32(cs->client_id);
 
	p->Send_uint32(_settings_game.game_creation.generation_seed);
 
	p->Send_string(_settings_client.network.network_id);
 
	cs->Send_Packet(p);
 

	
 
		/* Transmit info about all the active clients */
 
	FOR_ALL_CLIENT_SOCKETS(new_cs) {
 
		if (new_cs != cs && new_cs->status > STATUS_AUTH)
 
		if (new_cs != cs && new_cs->status > STATUS_AUTHORIZED)
 
			SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, new_cs->GetInfo());
 
	}
 
	/* Also send the info of the server */
 
	return SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, NetworkFindClientInfoFromClientID(CLIENT_ID_SERVER));
 
}
 

	
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WAIT)
 
{
 
	/*
 
	 * Packet: PACKET_SERVER_WAIT
 
	 * 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;
 
	NetworkClientSocket *new_cs;
 
	Packet *p;
 

	
 
	/* Count how many clients are waiting in the queue */
 
	FOR_ALL_CLIENT_SOCKETS(new_cs) {
 
		if (new_cs->status == STATUS_MAP_WAIT) waiting++;
 
	}
 

	
 
@@ -304,54 +304,54 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WA
 
	cs->Send_Packet(p);
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
/* This sends the map to the client */
 
DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
 
{
 
	/*
 
	 * Packet: SERVER_MAP
 
	 * Function: Sends the map to the client, or a part of it (it is splitted in
 
	 *   a lot of multiple packets)
 
	 * Data:
 
	 *    uint8:  packet-type (MAP_PACKET_START, MAP_PACKET_NORMAL and MAP_PACKET_END)
 
	 *  if MAP_PACKET_START:
 
	 *    uint32: The current FrameCounter
 
	 *  if MAP_PACKET_NORMAL:
 
	 *    piece of the map (till max-size of packet)
 
	 *  if MAP_PACKET_END:
 
	 *    nothing
 
	 */
 

	
 
	static FILE *file_pointer;
 
	static uint sent_packets; // How many packets we did send succecfully last time
 

	
 
	if (cs->status < STATUS_AUTH) {
 
	if (cs->status < STATUS_AUTHORIZED) {
 
		/* Illegal call, return error and ignore the packet */
 
		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
 
	}
 

	
 
	if (cs->status == STATUS_AUTH) {
 
	if (cs->status == STATUS_AUTHORIZED) {
 
		const char *filename = "network_server.tmp";
 
		Packet *p;
 

	
 
		/* Make a dump of the current game */
 
		if (SaveOrLoad(filename, SL_SAVE, AUTOSAVE_DIR) != SL_OK) usererror("network savedump failed");
 

	
 
		file_pointer = FioFOpenFile(filename, "rb", AUTOSAVE_DIR);
 
		fseek(file_pointer, 0, SEEK_END);
 

	
 
		if (ftell(file_pointer) == 0) usererror("network savedump failed - zero sized savegame?");
 

	
 
		/* Now send the _frame_counter and how many packets are coming */
 
		p = new Packet(PACKET_SERVER_MAP);
 
		p->Send_uint8 (MAP_PACKET_START);
 
		p->Send_uint32(_frame_counter);
 
		p->Send_uint32(ftell(file_pointer));
 
		cs->Send_Packet(p);
 

	
 
		fseek(file_pointer, 0, SEEK_SET);
 

	
 
		sent_packets = 4; // We start with trying 4 packets
 

	
 
		cs->status = STATUS_MAP;
 
		/* Mark the start of download */
 
@@ -370,49 +370,49 @@ DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MA
 
			if (ferror(file_pointer)) usererror("Error reading temporary network savegame!");
 

	
 
			p->size += res;
 
			cs->Send_Packet(p);
 
			if (feof(file_pointer)) {
 
				/* Done reading! */
 
				Packet *p = new Packet(PACKET_SERVER_MAP);
 
				p->Send_uint8(MAP_PACKET_END);
 
				cs->Send_Packet(p);
 

	
 
				/* 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);
 

	
 
				NetworkClientSocket *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_CLIENT_SOCKETS(new_cs) {
 
					if (new_cs->status == STATUS_MAP_WAIT) {
 
						/* Check if we already have a new client to send the map to */
 
						if (!new_map_client) {
 
							/* If not, this client will get the map */
 
							new_cs->status = STATUS_AUTH;
 
							new_cs->status = STATUS_AUTHORIZED;
 
							new_map_client = true;
 
							SEND_COMMAND(PACKET_SERVER_MAP)(new_cs);
 
						} else {
 
							/* Else, send the other clients how many clients are in front of them */
 
							SEND_COMMAND(PACKET_SERVER_WAIT)(new_cs);
 
						}
 
					}
 
				}
 

	
 
				/* There is no more data, so break the for */
 
				break;
 
			}
 
		}
 

	
 
		/* Send all packets (forced) and check if we have send it all */
 
		cs->Send_Packets();
 
		if (cs->IsPacketQueueEmpty()) {
 
			/* All are sent, increase the sent_packets */
 
			sent_packets *= 2;
 
		} else {
 
			/* Not everything is sent, decrease the sent_packets */
 
			if (sent_packets > 1) sent_packets /= 2;
 
		}
 
	}
 
@@ -794,90 +794,90 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
{
 
	NetworkClientSocket *new_cs;
 

	
 
	/* Do an extra version match. We told the client our version already,
 
	 * lets confirm that the client isn't lieing to us.
 
	 * But only do it for stable releases because of those we are sure
 
	 * that everybody has the same NewGRF version. For trunk and the
 
	 * branches we make tarballs of the OpenTTDs compiled from tarball
 
	 * will have the lower bits set to 0. As such they would become
 
	 * incompatible, which we would like to prevent by this. */
 
	if (HasBit(_openttd_newgrf_version, 19)) {
 
		if (_openttd_newgrf_version != p->Recv_uint32()) {
 
			/* The version we get from the client differs, it must have the
 
			 * wrong version. The client must be wrong. */
 
			return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 
		}
 
	} else if (p->size != 3) {
 
		/* We received a packet from a version that claims to be stable.
 
		 * That shouldn't happen. The client must be wrong. */
 
		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 
	}
 

	
 
	/* 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->HasClientQuit()) {
 
	if (cs->status < STATUS_AUTHORIZED || cs->HasClientQuit()) {
 
		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
 
	}
 

	
 
	/* Check if someone else is receiving the map */
 
	FOR_ALL_CLIENT_SOCKETS(new_cs) {
 
		if (new_cs->status == STATUS_MAP) {
 
			/* Tell the new client to wait */
 
			cs->status = STATUS_MAP_WAIT;
 
			return SEND_COMMAND(PACKET_SERVER_WAIT)(cs);
 
		}
 
	}
 

	
 
	/* We receive a request to upload the map.. give it to the client! */
 
	return SEND_COMMAND(PACKET_SERVER_MAP)(cs);
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
 
{
 
	/* Client has the map, now start syncing */
 
	if (cs->status == STATUS_DONE_MAP && !cs->HasClientQuit()) {
 
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 
		NetworkClientSocket *new_cs;
 

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

	
 
		NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, NULL, cs->client_id);
 

	
 
		/* Mark the client as pre-active, and wait for an ACK
 
		 *  so we know he is done loading and in sync with us */
 
		cs->status = STATUS_PRE_ACTIVE;
 
		NetworkHandleCommandQueue(cs);
 
		SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
 
		SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
 

	
 
		/* This is the frame the client receives
 
		 *  we need it later on to make sure the client is not too slow */
 
		cs->last_frame = _frame_counter;
 
		cs->last_frame_server = _frame_counter;
 

	
 
		FOR_ALL_CLIENT_SOCKETS(new_cs) {
 
			if (new_cs->status > STATUS_AUTH) {
 
			if (new_cs->status > STATUS_AUTHORIZED) {
 
				SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, cs->GetInfo());
 
				SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->client_id);
 
			}
 
		}
 

	
 
		/* also update the new client with our max values */
 
		SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)(cs);
 

	
 
		/* quickly update the syncing client with company details */
 
		return SEND_COMMAND(PACKET_SERVER_COMPANY_UPDATE)(cs);
 
	}
 

	
 
	/* Wrong status for this packet, give a warning to client, and close connection */
 
	return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
 
}
 

	
 
/** The client has done a command and wants us to handle it
 
 * @param *cs the connected client that has sent the command
 
 * @param *p the packet in which the command was sent
 
 */
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
 
{
 
	NetworkClientSocket *new_cs;
 

	
 
@@ -968,87 +968,87 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
{
 
	/* This packets means a client noticed an error and is reporting this
 
	 *  to us. Display the error and report it to the other clients */
 
	NetworkClientSocket *new_cs;
 
	char str[100];
 
	char client_name[NETWORK_CLIENT_NAME_LENGTH];
 
	NetworkErrorCode errorno = (NetworkErrorCode)p->Recv_uint8();
 

	
 
	/* The client was never joined.. thank the client for the packet, but ignore it */
 
	if (cs->status < STATUS_DONE_MAP || cs->HasClientQuit()) {
 
		cs->CloseConnection();
 
		return NETWORK_RECV_STATUS_CONN_LOST;
 
	}
 

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

	
 
	StringID strid = GetNetworkErrorMsg(errorno);
 
	GetString(str, strid, lastof(str));
 

	
 
	DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
 

	
 
	NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, strid);
 

	
 
	FOR_ALL_CLIENT_SOCKETS(new_cs) {
 
		if (new_cs->status > STATUS_AUTH) {
 
		if (new_cs->status > STATUS_AUTHORIZED) {
 
			SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, errorno);
 
		}
 
	}
 

	
 
	cs->CloseConnection(false);
 
	return NETWORK_RECV_STATUS_CONN_LOST;
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
 
{
 
	/* The client wants to leave. Display this and report it to the other
 
	 *  clients. */
 
	NetworkClientSocket *new_cs;
 
	char client_name[NETWORK_CLIENT_NAME_LENGTH];
 

	
 
	/* The client was never joined.. thank the client for the packet, but ignore it */
 
	if (cs->status < STATUS_DONE_MAP || cs->HasClientQuit()) {
 
		cs->CloseConnection();
 
		return NETWORK_RECV_STATUS_CONN_LOST;
 
	}
 

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

	
 
	NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
 

	
 
	FOR_ALL_CLIENT_SOCKETS(new_cs) {
 
		if (new_cs->status > STATUS_AUTH) {
 
		if (new_cs->status > STATUS_AUTHORIZED) {
 
			SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->client_id);
 
		}
 
	}
 

	
 
	cs->CloseConnection(false);
 
	return NETWORK_RECV_STATUS_CONN_LOST;
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
 
{
 
	if (cs->status < STATUS_AUTH) {
 
	if (cs->status < STATUS_AUTHORIZED) {
 
		/* Illegal call, return error and ignore the packet */
 
		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
 
	}
 

	
 
	uint32 frame = p->Recv_uint32();
 

	
 
	/* The client is trying to catch up with the server */
 
	if (cs->status == STATUS_PRE_ACTIVE) {
 
		/* The client is not yet catched up? */
 
		if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY;
 

	
 
		/* Now he is! Unpause the game */
 
		cs->status = STATUS_ACTIVE;
 

	
 
		/* Execute script for, e.g. MOTD */
 
		IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
 
	}
 

	
 
	/* The client received the frame, make note of it */
 
	cs->last_frame = frame;
 
	/* With those 2 values we can calculate the lag realtime */
 
	cs->last_frame_server = _frame_counter;
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 
@@ -1133,49 +1133,49 @@ void NetworkServerSendChat(NetworkAction
 
					if (cs->client_id == from_id) {
 
						SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, ci_to->client_id, true, msg, data);
 
					}
 
				}
 
			}
 
		}
 
		}
 
		break;
 
	default:
 
		DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
 
		/* fall-through to next case */
 
	case DESTTYPE_BROADCAST:
 
		FOR_ALL_CLIENT_SOCKETS(cs) {
 
			SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_id, false, msg, data);
 
		}
 
		ci = NetworkFindClientInfoFromClientID(from_id);
 
		if (ci != NULL)
 
			NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
 
		break;
 
	}
 
}
 

	
 
DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
 
{
 
	if (cs->status < STATUS_AUTH) {
 
	if (cs->status < STATUS_AUTHORIZED) {
 
		/* Illegal call, return error and ignore the packet */
 
		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
 
	}
 

	
 
	NetworkAction action = (NetworkAction)p->Recv_uint8();
 
	DestType desttype = (DestType)p->Recv_uint8();
 
	int dest = p->Recv_uint32();
 
	char msg[NETWORK_CHAT_LENGTH];
 

	
 
	p->Recv_string(msg, NETWORK_CHAT_LENGTH);
 
	int64 data = p->Recv_uint64();
 

	
 
	NetworkClientInfo *ci = cs->GetInfo();
 
	switch (action) {
 
		case NETWORK_ACTION_GIVE_MONEY:
 
			if (!Company::IsValidID(ci->client_playas)) break;
 
			/* Fall-through */
 
		case NETWORK_ACTION_CHAT:
 
		case NETWORK_ACTION_CHAT_CLIENT:
 
		case NETWORK_ACTION_CHAT_COMPANY:
 
			NetworkServerSendChat(action, desttype, dest, msg, cs->client_id, data);
 
			break;
 
		default:
 
			IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, GetClientIP(ci));
0 comments (0 inline, 0 general)