(svn r9344) [0.5] -Backport from trunk (r9027, r9038, r9061, r9071): 0.5
authorrubidium
Mon, 19 Mar 2007 19:34:44 +0000
branch0.5
changeset 5462 6d16b7e4f85d
parent 5461 03285c9589f9
child 5463 eaf87cf4d276
(svn r9344) [0.5] -Backport from trunk (r9027, r9038, r9061, r9071):
- Fix: desync caused by buffer overflow (r9027)
- Feature: kick inactive initial network connections after some time (r9038, r9061)
- Fix: take over companies properly in multiplayer games (r9071)
console_cmds.c
currency.c
economy.c
network_data.h
network_server.c
--- a/console_cmds.c	Mon Mar 19 19:22:26 2007 +0000
+++ b/console_cmds.c	Mon Mar 19 19:34:44 2007 +0000
@@ -529,6 +529,7 @@
 {
 	static const char* const stat_str[] = {
 		"inactive",
+		"authorizing",
 		"authorized",
 		"waiting",
 		"loading map",
--- a/currency.c	Mon Mar 19 19:22:26 2007 +0000
+++ b/currency.c	Mon Mar 19 19:34:44 2007 +0000
@@ -168,7 +168,7 @@
 StringID* BuildCurrencyDropdown(void)
 {
 	/* Allow room for all currencies, plus a terminator entry */
-	static StringID names[CUSTOM_CURRENCY_ID];
+	static StringID names[NUM_CURRENCY + 1];
 	uint i;
 
 	/* Add each name */
--- a/economy.c	Mon Mar 19 19:22:26 2007 +0000
+++ b/economy.c	Mon Mar 19 19:34:44 2007 +0000
@@ -362,6 +362,40 @@
 	MarkWholeScreenDirty();
 }
 
+static void ChangeNetworkOwner(PlayerID current_player, PlayerID new_player)
+{
+#ifdef ENABLE_NETWORK
+	if (!_networking) return;
+
+	if (current_player == _local_player) {
+		_network_playas = new_player;
+		SetLocalPlayer(new_player);
+	}
+
+	if (!_network_server) return;
+
+	/* The server has to handle all administrative issues, for example
+	* updating and notifying all clients of what has happened */
+	NetworkClientState *cs;
+	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+
+	/* The server has just changed from player */
+	if (current_player == ci->client_playas) {
+		ci->client_playas = new_player;
+		NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
+	}
+
+	/* Find all clients that were in control of this company, and mark them as new_player */
+	FOR_ALL_CLIENTS(cs) {
+		ci = DEREF_CLIENT_INFO(cs);
+		if (current_player == ci->client_playas) {
+			ci->client_playas = new_player;
+			NetworkUpdateClientInfo(ci->client_index);
+		}
+	}
+#endif /* ENABLE_NETWORK */
+}
+
 static void PlayersCheckBankrupt(Player *p)
 {
 	PlayerID owner;
@@ -419,35 +453,9 @@
 					p->bankrupt_asked = 0xFF;
 					p->bankrupt_timeout = 0x456;
 					break;
-				} else if (owner == _local_player) {
-					_network_playas = PLAYER_SPECTATOR;
-					SetLocalPlayer(PLAYER_SPECTATOR);
 				}
 
-#ifdef ENABLE_NETWORK
-				/* The server has to handle all administrative issues, for example
-				 * updating and notifying all clients of what has happened */
-				if (_network_server) {
-					const NetworkClientState *cs;
-					NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
-
-					/* The server has just gone belly-up, mark it as spectator */
-					if (owner == ci->client_playas) {
-						ci->client_playas = PLAYER_SPECTATOR;
-						NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
-					}
-
-					/* Find all clients that were in control of this company,
-					 * and mark them as spectator; broadcast this message to everyone */
-					FOR_ALL_CLIENTS(cs) {
-						ci = DEREF_CLIENT_INFO(cs);
-						if (ci->client_playas == owner) {
-							ci->client_playas = PLAYER_SPECTATOR;
-							NetworkUpdateClientInfo(ci->client_index);
-						}
-					}
-				}
-#endif /* ENABLE_NETWORK */
+				ChangeNetworkOwner(owner, PLAYER_SPECTATOR);
 			}
 
 			/* Remove the player */
@@ -1572,6 +1580,7 @@
 
 	// original code does this a little bit differently
 	pi = p->index;
+	ChangeNetworkOwner(pi, _current_player);
 	ChangeOwnershipOfPlayerItems(pi, _current_player);
 
 	if (p->bankrupt_value == 0) {
--- a/network_data.h	Mon Mar 19 19:22:26 2007 +0000
+++ b/network_data.h	Mon Mar 19 19:34:44 2007 +0000
@@ -49,6 +49,7 @@
 
 typedef enum {
 	STATUS_INACTIVE,
+	STATUS_AUTHORIZING, // This means that the client is authorizing
 	STATUS_AUTH, // This means that the client is authorized
 	STATUS_MAP_WAIT, // This means that the client is put on hold because someone else is getting the map
 	STATUS_MAP,
--- a/network_server.c	Mon Mar 19 19:22:26 2007 +0000
+++ b/network_server.c	Mon Mar 19 19:34:44 2007 +0000
@@ -215,7 +215,14 @@
 	//    uint8:  Type of password
 	//
 
-	Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
+	Packet *p;
+
+	/* Invalid packet when status is AUTH or higher */
+	if (cs->status >= STATUS_AUTH) return;
+
+	cs->status = STATUS_AUTHORIZING;
+
+	p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
 	NetworkSend_uint8(p, type);
 	NetworkSend_Packet(p, cs);
 }
@@ -694,7 +701,7 @@
 	type = NetworkRecv_uint8(cs, p);
 	NetworkRecv_string(cs, p, password, sizeof(password));
 
-	if (cs->status == STATUS_INACTIVE && type == NETWORK_GAME_PASSWORD) {
+	if (cs->status == STATUS_AUTHORIZING && type == NETWORK_GAME_PASSWORD) {
 		// Check game-password
 		if (strcmp(password, _network_game_info.server_password) != 0) {
 			// Password is invalid
@@ -712,7 +719,7 @@
 		// Valid password, allow user
 		SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
 		return;
-	} else if (cs->status == STATUS_INACTIVE && type == NETWORK_COMPANY_PASSWORD) {
+	} else if (cs->status == STATUS_AUTHORIZING && type == NETWORK_COMPANY_PASSWORD) {
 		ci = DEREF_CLIENT_INFO(cs);
 
 		if (strcmp(password, _network_player_info[ci->client_playas].password) != 0) {
@@ -1534,6 +1541,12 @@
 				IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
 				NetworkCloseClient(cs);
 			}
+		} else if (cs->status == STATUS_INACTIVE) {
+			int lag = NetworkCalculateLag(cs);
+			if (lag > 4 * DAY_TICKS) {
+				IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS);
+				NetworkCloseClient(cs);
+			}
 		}
 
 		if (cs->status >= STATUS_PRE_ACTIVE) {