about summary refs log tree commit diff
path: root/src/engine/server
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2008-02-10 21:54:52 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2008-02-10 21:54:52 +0000
commit548a919ea379a3b9d1d9e41cf4dad6b4779fd3e6 (patch)
tree85666198fed3d4803f3ec3373c134d12bde9329b /src/engine/server
parent2f969d9d6fece689e05857580ffb1843439e5fbb (diff)
downloadzcatch-548a919ea379a3b9d1d9e41cf4dad6b4779fd3e6.tar.gz
zcatch-548a919ea379a3b9d1d9e41cf4dad6b4779fd3e6.zip
merged 0.3.4 changes to trunk
Diffstat (limited to 'src/engine/server')
-rw-r--r--src/engine/server/es_register.c258
-rw-r--r--src/engine/server/es_server.c100
2 files changed, 278 insertions, 80 deletions
diff --git a/src/engine/server/es_register.c b/src/engine/server/es_register.c
new file mode 100644
index 00000000..c7f4bcc9
--- /dev/null
+++ b/src/engine/server/es_register.c
@@ -0,0 +1,258 @@
+#include <string.h>
+#include <engine/e_system.h>
+#include <engine/e_network.h>
+#include <engine/e_config.h>
+#include <engine/e_engine.h>
+
+#include <mastersrv/mastersrv.h>
+
+extern NETSERVER *net;
+
+enum
+{
+	REGISTERSTATE_START=0,
+	REGISTERSTATE_UPDATE_ADDRS,
+	REGISTERSTATE_QUERY_COUNT,
+	REGISTERSTATE_HEARTBEAT,
+	REGISTERSTATE_REGISTERED,
+	REGISTERSTATE_ERROR
+};
+
+static int register_state = REGISTERSTATE_START;
+static int64 register_state_start = 0;
+static int register_first = 1;
+
+static void register_new_state(int state)
+{
+	register_state = state;
+	register_state_start = time_get();
+}
+
+static void register_send_fwcheckresponse(NETADDR4 *addr)
+{
+	NETPACKET packet;
+	packet.client_id = -1;
+	packet.address = *addr;
+	packet.flags = PACKETFLAG_CONNLESS;
+	packet.data_size = sizeof(SERVERBROWSE_FWRESPONSE);
+	packet.data = SERVERBROWSE_FWRESPONSE;
+	netserver_send(net, &packet);
+}
+	
+static void register_send_heartbeat(NETADDR4 addr)
+{
+	static unsigned char data[sizeof(SERVERBROWSE_HEARTBEAT) + 2];
+	unsigned short port = config.sv_port;
+	NETPACKET packet;
+	
+	mem_copy(data, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT));
+	
+	packet.client_id = -1;
+	packet.address = addr;
+	packet.flags = PACKETFLAG_CONNLESS;
+	packet.data_size = sizeof(SERVERBROWSE_HEARTBEAT) + 2;
+	packet.data = &data;
+
+	/* supply the set port that the master can use if it has problems */	
+	if(config.sv_external_port)
+		port = config.sv_external_port;
+	data[sizeof(SERVERBROWSE_HEARTBEAT)] = port >> 8;
+	data[sizeof(SERVERBROWSE_HEARTBEAT)+1] = port&0xff;
+	netserver_send(net, &packet);
+}
+
+static void register_send_count_request(NETADDR4 addr)
+{
+	NETPACKET packet;
+	packet.client_id = -1;
+	packet.address = addr;
+	packet.flags = PACKETFLAG_CONNLESS;
+	packet.data_size = sizeof(SERVERBROWSE_GETCOUNT);
+	packet.data = SERVERBROWSE_GETCOUNT;
+	netserver_send(net, &packet);
+}
+
+typedef struct
+{
+	NETADDR4 addr;
+	int count;
+	int valid;
+	int64 last_send;
+} MASTERSERVER_INFO;
+
+static MASTERSERVER_INFO masterserver_info[MAX_MASTERSERVERS] = {{{{0}}}};
+static int register_registered_server = -1;
+
+void register_update()
+{
+	int64 now = time_get();
+	int64 freq = time_freq();
+	mastersrv_update();
+	
+	if(register_state == REGISTERSTATE_START)
+	{
+		register_first = 1;
+		register_new_state(REGISTERSTATE_UPDATE_ADDRS);
+		mastersrv_refresh_addresses();
+		dbg_msg("register", "refreshing ip addresses");
+	}
+	else if(register_state == REGISTERSTATE_UPDATE_ADDRS)
+	{
+		register_registered_server = -1;
+		
+		if(!mastersrv_refreshing())
+		{
+			int i;
+			for(i = 0; i < MAX_MASTERSERVERS; i++)
+			{
+				NETADDR4 addr = mastersrv_get(i);
+				masterserver_info[i].addr = addr;
+				masterserver_info[i].count = 0;
+				
+				if(!addr.ip[0] && !addr.ip[1] && !addr.ip[2] && !addr.ip[3])
+					masterserver_info[i].valid = 0;
+				else
+				{
+					masterserver_info[i].valid = 1;
+					masterserver_info[i].count = -1;
+					masterserver_info[i].last_send = 0;
+				}
+			}
+			
+			dbg_msg("register", "fetching server counts");
+			register_new_state(REGISTERSTATE_QUERY_COUNT);
+		}
+	}
+	else if(register_state == REGISTERSTATE_QUERY_COUNT)
+	{
+		int i;
+		int left = 0;
+		for(i = 0; i < MAX_MASTERSERVERS; i++)
+		{
+			if(!masterserver_info[i].valid)
+				continue;
+				
+			if(masterserver_info[i].count == -1)
+			{
+				left++;
+				if(masterserver_info[i].last_send+freq < now)
+				{
+					masterserver_info[i].last_send = now;
+					register_send_count_request(masterserver_info[i].addr);
+				}
+			}
+		}
+		
+		/* check if we are done or timed out */
+		if(left == 0 || now > register_state_start+freq*3)
+		{
+			/* choose server */
+			int best = -1;
+			int i;
+			for(i = 0; i < MAX_MASTERSERVERS; i++)
+			{
+				if(!masterserver_info[i].valid || masterserver_info[i].count == -1)
+					continue;
+					
+				if(best == -1 || masterserver_info[i].count < masterserver_info[best].count)
+					best = i;
+			}
+
+			/* server chosen */
+			register_registered_server = best;
+			if(register_registered_server == -1)
+			{
+				dbg_msg("register", "WARNING: No master servers. Retrying in 60 seconds");
+				register_new_state(REGISTERSTATE_ERROR);
+			}
+			else
+			{			
+				dbg_msg("register", "choosen '%s' as master, sending heartbeats", mastersrv_name(register_registered_server));
+				masterserver_info[register_registered_server].last_send = 0;
+				register_new_state(REGISTERSTATE_HEARTBEAT);
+			}
+		}
+	}
+	else if(register_state == REGISTERSTATE_HEARTBEAT)
+	{
+		/* check if we should send heartbeat */
+		if(now > masterserver_info[register_registered_server].last_send+freq*15)
+		{
+			masterserver_info[register_registered_server].last_send = now;
+			register_send_heartbeat(masterserver_info[register_registered_server].addr);
+		}
+		
+		if(now > register_state_start+freq*60)
+		{
+			dbg_msg("register", "WARNING: Master server is not responding, switching master");
+			register_new_state(REGISTERSTATE_START);
+		}
+	}
+	else if(register_state == REGISTERSTATE_REGISTERED)
+	{
+		if(register_first)
+			dbg_msg("register", "server registered");
+			
+		register_first = 0;
+		
+		/* check if we should send new heartbeat again */
+		if(now > register_state_start+freq*30)
+			register_new_state(REGISTERSTATE_HEARTBEAT);
+	}
+	else if(register_state == REGISTERSTATE_ERROR)
+	{
+		/* check for restart */
+		if(now > register_state_start+freq*60)
+			register_new_state(REGISTERSTATE_START);
+	}
+}
+
+static void register_got_count(NETPACKET *p)
+{
+	unsigned char *data = (unsigned char *)p->data;
+	int count = (data[sizeof(SERVERBROWSE_COUNT)]<<8) | data[sizeof(SERVERBROWSE_COUNT)+1];
+	int i;
+
+	for(i = 0; i < MAX_MASTERSERVERS; i++)
+	{
+		if(net_addr4_cmp(&masterserver_info[i].addr, &p->address) == 0)
+		{
+			masterserver_info[i].count = count;
+			break;
+		}
+	}
+}
+
+int register_process_packet(NETPACKET *packet)
+{
+	if(packet->data_size == sizeof(SERVERBROWSE_FWCHECK) &&
+		memcmp(packet->data, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0)
+	{
+		register_send_fwcheckresponse(&packet->address);
+		return 1;
+	}
+	else if(packet->data_size == sizeof(SERVERBROWSE_FWOK) &&
+		memcmp(packet->data, SERVERBROWSE_FWOK, sizeof(SERVERBROWSE_FWOK)) == 0)
+	{
+		if(register_first)
+			dbg_msg("register", "no firewall/nat problems detected");
+		register_new_state(REGISTERSTATE_REGISTERED);
+		return 1;
+	}
+	else if(packet->data_size == sizeof(SERVERBROWSE_FWERROR) &&
+		memcmp(packet->data, SERVERBROWSE_FWERROR, sizeof(SERVERBROWSE_FWERROR)) == 0)
+	{
+		dbg_msg("register", "ERROR: the master server reports that clients can not connect to this server.");
+		dbg_msg("register", "ERROR: configure your firewall/nat to let trough udp on port %d.", config.sv_port);
+		register_new_state(REGISTERSTATE_ERROR);
+		return 1;
+	}
+	else if(packet->data_size == sizeof(SERVERBROWSE_COUNT)+2 &&
+		memcmp(packet->data, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)) == 0)
+	{
+		register_got_count(packet);
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/src/engine/server/es_server.c b/src/engine/server/es_server.c
index c677d154..415b67fe 100644
--- a/src/engine/server/es_server.c
+++ b/src/engine/server/es_server.c
@@ -29,7 +29,7 @@ static int browseinfo_gametype = -1;
 static int browseinfo_progression = -1;
 
 static int64 lastheartbeat;
-static NETADDR4 master_server;
+/*static NETADDR4 master_server;*/
 
 static char current_map[64];
 static int current_map_crc;
@@ -101,7 +101,7 @@ typedef struct
 } CLIENT;
 
 static CLIENT clients[MAX_CLIENTS];
-static NETSERVER *net;
+NETSERVER *net;
 
 static void snap_init_id()
 {
@@ -535,29 +535,6 @@ static void server_send_map(int cid)
 	msg_pack_end();
 	server_send_msg(cid);
 }
-	
-static void server_send_heartbeat()
-{
-	static unsigned char data[sizeof(SERVERBROWSE_HEARTBEAT) + 2];
-	unsigned short port = config.sv_port;
-	NETPACKET packet;
-	
-	mem_copy(data, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT));
-	
-	packet.client_id = -1;
-	packet.address = master_server;
-	packet.flags = PACKETFLAG_CONNLESS;
-	packet.data_size = sizeof(SERVERBROWSE_HEARTBEAT) + 2;
-	packet.data = &data;
-
-	/* supply the set port that the master can use if it has problems */	
-	if(config.sv_external_port)
-		port = config.sv_external_port;
-	data[sizeof(SERVERBROWSE_HEARTBEAT)] = port >> 8;
-	data[sizeof(SERVERBROWSE_HEARTBEAT)+1] = port&0xff;
-	
-	netserver_send(net, &packet);
-}
 
 static void server_process_client_packet(NETPACKET *packet)
 {
@@ -631,7 +608,7 @@ static void server_process_client_packet(NETPACKET *packet)
 		}
 		else if(msg == NETMSG_ENTERGAME)
 		{
-			if(clients[cid].state != SRVCLIENT_STATE_INGAME)
+			if(clients[cid].state == SRVCLIENT_STATE_READY)
 			{
 				dbg_msg("server", "player as entered the game. cid=%x", cid);
 				clients[cid].state = SRVCLIENT_STATE_INGAME;
@@ -783,18 +760,8 @@ static void server_dump_status()
 }
 			
 
-
-
-static void server_send_fwcheckresponse(NETADDR4 *addr)
-{
-	NETPACKET packet;
-	packet.client_id = -1;
-	packet.address = *addr;
-	packet.flags = PACKETFLAG_CONNLESS;
-	packet.data_size = sizeof(SERVERBROWSE_FWRESPONSE);
-	packet.data = SERVERBROWSE_FWRESPONSE;
-	netserver_send(net, &packet);
-}
+extern int register_process_packet(NETPACKET *packet);
+extern int register_update();
 
 static void server_pump_network()
 {
@@ -808,32 +775,18 @@ static void server_pump_network()
 		if(packet.client_id == -1)
 		{
 			/* stateless */
-			if(packet.data_size == sizeof(SERVERBROWSE_GETINFO) &&
-				memcmp(packet.data, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0)
-			{
-				server_send_serverinfo(&packet.address, 0);
-			}
-			else if(packet.data_size == sizeof(SERVERBROWSE_GETINFO_LAN) &&
-				memcmp(packet.data, SERVERBROWSE_GETINFO_LAN, sizeof(SERVERBROWSE_GETINFO_LAN)) == 0)
+			if(!register_process_packet(&packet))
 			{
-				server_send_serverinfo(&packet.address, 1);
-			}
-			else if(packet.data_size == sizeof(SERVERBROWSE_FWCHECK) &&
-				memcmp(packet.data, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0)
-			{
-				server_send_fwcheckresponse(&packet.address);
-			}
-			else if(packet.data_size == sizeof(SERVERBROWSE_FWOK) &&
-				memcmp(packet.data, SERVERBROWSE_FWOK, sizeof(SERVERBROWSE_FWOK)) == 0)
-			{
-				if(config.debug)
-					dbg_msg("server", "no firewall/nat problems detected");
-			}
-			else if(packet.data_size == sizeof(SERVERBROWSE_FWERROR) &&
-				memcmp(packet.data, SERVERBROWSE_FWERROR, sizeof(SERVERBROWSE_FWERROR)) == 0)
-			{
-				dbg_msg("server", "ERROR: the master server reports that clients can not connect to this server.");
-				dbg_msg("server", "ERROR: configure your firewall/nat to let trough udp on port %d.", config.sv_port);
+				if(packet.data_size == sizeof(SERVERBROWSE_GETINFO) &&
+					memcmp(packet.data, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0)
+				{
+					server_send_serverinfo(&packet.address, 0);
+				}
+				else if(packet.data_size == sizeof(SERVERBROWSE_GETINFO_LAN) &&
+					memcmp(packet.data, SERVERBROWSE_GETINFO_LAN, sizeof(SERVERBROWSE_GETINFO_LAN)) == 0)
+				{
+					server_send_serverinfo(&packet.address, 1);
+				}
 			}
 		}
 		else
@@ -873,7 +826,6 @@ static int server_load_map(const char *mapname)
 	return 1;
 }
 
-
 static int server_run()
 {
 	NETADDR4 bindaddr;
@@ -910,19 +862,12 @@ static int server_run()
 	netserver_set_callbacks(net, new_client_callback, del_client_callback, 0);
 	
 	dbg_msg("server", "server name is '%s'", config.sv_name);
-	dbg_msg("server", "masterserver is '%s'", config.masterserver);
-	if(net_host_lookup(config.masterserver, MASTERSERVER_PORT, &master_server) != 0)
-	{
-		/* TODO: fix me */
-		/*master_server = netaddr4(0, 0, 0, 0, 0); */
-	}
-
+	
 	mods_init();
 	dbg_msg("server", "version %s", mods_net_version());
 
 	/* start game */
 	{
-		int64 time_per_heartbeat = time_freq() * 30;
 		int64 reporttime = time_get();
 		int reportinterval = 3;
 	
@@ -1025,15 +970,10 @@ static int server_run()
 					perf_end();
 				}
 			}
+			
+			/* master server stuff */
+			register_update();
 	
-			if(config.sv_sendheartbeats)
-			{
-				if (t > lastheartbeat+time_per_heartbeat)
-				{
-					server_send_heartbeat();
-					lastheartbeat = t+time_per_heartbeat;
-				}
-			}
 
 			{
 				static PERFORMACE_INFO scope = {"net", 0};