about summary refs log tree commit diff
path: root/src/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/client/client.c272
-rw-r--r--src/engine/interface.h17
-rw-r--r--src/engine/memheap.c101
-rw-r--r--src/engine/memheap.h5
-rw-r--r--src/engine/server/server.c2
5 files changed, 325 insertions, 72 deletions
diff --git a/src/engine/client/client.c b/src/engine/client/client.c
index a518fe39..47175ca6 100644
--- a/src/engine/client/client.c
+++ b/src/engine/client/client.c
@@ -15,6 +15,7 @@
 #include <engine/network.h>
 #include <engine/config.h>
 #include <engine/packer.h>
+#include <engine/memheap.h>
 
 #include <mastersrv/mastersrv.h>
 
@@ -31,8 +32,6 @@ const int prediction_margin = 5;
 	Prediction Latency
 		Upstream latency
 */
-static int info_request_begin;
-static int info_request_end;
 static int snapshot_part;
 static int64 local_start_time;
 
@@ -346,29 +345,119 @@ int *client_get_input(int tick)
 }
 
 // ------ server browse ----
-static struct 
+typedef struct SERVERENTRY_t SERVERENTRY;
+struct SERVERENTRY_t
 {
-	SERVER_INFO infos[MAX_SERVERS];
-	int64 request_times[MAX_SERVERS];
-	NETADDR4 addresses[MAX_SERVERS];
-	int num;
-} servers;
+	NETADDR4 addr;
+	int64 request_time;
+	SERVER_INFO info;
+	
+	SERVERENTRY *next_ip; // ip hashed list
+	
+	SERVERENTRY *prev_req; // request list
+	SERVERENTRY *next_req;
+};
+
+HEAP *serverlist_heap = 0;
+SERVERENTRY **serverlist = 0;
+
+SERVERENTRY *serverlist_ip[256] = {0}; // ip hash list
+
+SERVERENTRY *first_req_server = 0; // request list
+SERVERENTRY *last_req_server = 0;
+
+int num_servers = 0;
+int num_server_capasity = 0;
 
 static int serverlist_lan = 1;
 
-int client_serverbrowse_getlist(SERVER_INFO **serverlist)
+SERVER_INFO *client_serverbrowse_get(int index)
 {
-	*serverlist = servers.infos;
-	return servers.num;
+	if(index < 0 || index >= num_servers)
+		return 0;
+	return &serverlist[index]->info;
+}
+
+int client_serverbrowse_num()
+{
+	return num_servers;
 }
 
 static void client_serverbrowse_init()
 {
-	servers.num = 0;
+}
+
+static void client_serverbrowse_set(NETADDR4 *addr, int request, SERVER_INFO *info)
+{
+	int hash = addr->ip[0];
+	SERVERENTRY *entry = serverlist_ip[hash];
+	while(entry)
+	{
+		if(net_addr4_cmp(&entry->addr, addr) == 0)
+		{
+			/* update the server that we already have */
+			entry->info = *info;
+			if(!request)
+				entry->info.latency = (time_get()-entry->request_time)*1000/time_freq();
+			return;
+		}
+		entry = entry->next_ip;
+	}
+
+	/* create new entry */	
+	entry = (SERVERENTRY *)memheap_allocate(serverlist_heap, sizeof(SERVERENTRY));
+	mem_zero(entry, sizeof(SERVERENTRY));
+	
+	/* set the info */
+	entry->addr = *addr;
+	entry->info = *info;
+
+	/* add to the hash list */	
+	entry->next_ip = serverlist_ip[hash];
+	serverlist_ip[hash] = entry;
+	
+	if(num_servers == num_server_capasity)
+	{
+		num_server_capasity += 100;
+		SERVERENTRY **newlist = mem_alloc(num_server_capasity*sizeof(SERVERENTRY*), 1);
+		memcpy(newlist, serverlist, num_servers*sizeof(SERVERENTRY*));
+		mem_free(serverlist);
+		serverlist = newlist;
+	}
+	
+	/* add to list */
+	serverlist[num_servers] = entry;
+	num_servers++;
+	
+	/* */
+	entry->prev_req = 0;
+	entry->next_req = 0;
+	
+	if(request)
+	{
+		/* add it to the list of servers that we should request info from */
+		entry->prev_req = last_req_server;
+		if(last_req_server)
+			last_req_server->next_req = entry;
+		else
+			first_req_server = entry;
+		last_req_server = entry;
+	}
 }
 
 void client_serverbrowse_refresh(int lan)
 {
+	/* clear out everything */
+	if(serverlist_heap)
+		memheap_destroy(serverlist_heap);
+	serverlist_heap = memheap_create();
+	num_servers = 0;
+	num_server_capasity = 0;
+	mem_zero(serverlist_ip, sizeof(serverlist_ip));
+	first_req_server = 0;
+	last_req_server = 0;
+	
+	/* */
 	serverlist_lan = lan;
 	
 	if(serverlist_lan)
@@ -389,7 +478,7 @@ void client_serverbrowse_refresh(int lan)
 		netclient_send(net, &packet);	
 		
 		// reset the list
-		servers.num = 0;		
+		//servers.num = 0;
 	}
 	else
 	{
@@ -405,27 +494,28 @@ void client_serverbrowse_refresh(int lan)
 		netclient_send(net, &packet);	
 		
 		// reset the list
-		servers.num = 0;
+		//servers.num = 0;
 	}
 }
 
 
-static void client_serverbrowse_request(int id)
+static void client_serverbrowse_request(SERVERENTRY *entry)
 {
 	if(config.debug)
 	{
 		dbg_msg("client", "requesting server info from %d.%d.%d.%d:%d",
-			servers.addresses[id].ip[0], servers.addresses[id].ip[1], servers.addresses[id].ip[2],
-			servers.addresses[id].ip[3], servers.addresses[id].port);
+			entry->addr.ip[0], entry->addr.ip[1], entry->addr.ip[2],
+			entry->addr.ip[3], entry->addr.port);
 	}
-	NETPACKET packet;
-	packet.client_id = -1;
-	packet.address = servers.addresses[id];
-	packet.flags = PACKETFLAG_CONNLESS;
-	packet.data_size = sizeof(SERVERBROWSE_GETINFO);
-	packet.data = SERVERBROWSE_GETINFO;
-	netclient_send(net, &packet);
-	servers.request_times[id] = time_get();
+	
+	NETPACKET p;
+	p.client_id = -1;
+	p.address = entry->addr;
+	p.flags = PACKETFLAG_CONNLESS;
+	p.data_size = sizeof(SERVERBROWSE_GETINFO);
+	p.data = SERVERBROWSE_GETINFO;
+	netclient_send(net, &p);
+	entry->request_time = time_get();
 }
 
 static void client_serverbrowse_update()
@@ -433,7 +523,55 @@ static void client_serverbrowse_update()
 	int64 timeout = time_freq();
 	int64 now = time_get();
 	int max_requests = 10;
+	int count;
+	
+	SERVERENTRY *entry, *next;
 	
+	/* do timeouts */
+	entry = first_req_server;
+	while(1)
+	{
+		if(!entry) // no more entries
+			break;
+			
+		next = entry->next_req;
+		
+		if(entry->request_time && entry->request_time+timeout < now)
+		{
+			/* timeout */
+			if(entry->prev_req)
+				entry->prev_req->next_req = entry->next_req;
+			else
+				first_req_server = entry->next_req;
+				
+			if(entry->next_req)
+				entry->next_req->prev_req = entry->prev_req;
+			else
+				last_req_server = entry->prev_req;
+		}
+			
+		entry = next;
+	}
+
+	/* do timeouts */
+	entry = first_req_server;
+	count = 0;
+	while(1)
+	{
+		if(!entry) // no more entries
+			break;
+			
+		if(count == max_requests) // no more then 10 concurrent requests
+			break;
+			
+		if(entry->request_time == 0)
+			client_serverbrowse_request(entry);
+		
+		count++;
+		entry = entry->next_req;
+	}
+		
+	/*
 	// timeout old requests
 	while(info_request_begin < servers.num && info_request_begin < info_request_end)
 	{
@@ -448,7 +586,7 @@ static void client_serverbrowse_update()
 	{
 		client_serverbrowse_request(info_request_end);
 		info_request_end++;
-	}
+	}*/
 }
 
 // ------ state handling -----
@@ -597,7 +735,30 @@ static void client_process_packet(NETPACKET *packet)
 		if(packet->data_size >= (int)sizeof(SERVERBROWSE_LIST) &&
 			memcmp(packet->data, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)) == 0)
 		{
+			int size = packet->data_size-sizeof(SERVERBROWSE_LIST);
+			//mem_copy(servers.addresses, (char*)packet->data+sizeof(SERVERBROWSE_LIST), size);
+			int num = size/sizeof(NETADDR4);
+			NETADDR4 *addrs = (NETADDR4 *)((char*)packet->data+sizeof(SERVERBROWSE_LIST));
+			
+			int i;
+			for(i = 0; i < num; i++)
+			{
+				NETADDR4 addr = addrs[i];
+				SERVER_INFO info = {0};
+				
+				info.latency = 999;
+				sprintf(info.address, "%d.%d.%d.%d:%d",
+					addr.ip[0], addr.ip[1], addr.ip[2],
+					addr.ip[3], addr.port);
+				sprintf(info.name, "%d.%d.%d.%d:%d",
+					addr.ip[0], addr.ip[1], addr.ip[2],
+					addr.ip[3], addr.port);
+				
+				client_serverbrowse_set(addrs+i, 1, &info);
+			}
+			
 			// server listing
+			/*
 			int size = packet->data_size-sizeof(SERVERBROWSE_LIST);
 			mem_copy(servers.addresses, (char*)packet->data+sizeof(SERVERBROWSE_LIST), size);
 			servers.num = size/sizeof(NETADDR4);
@@ -621,7 +782,7 @@ static void client_process_packet(NETPACKET *packet)
 				sprintf(servers.infos[i].name, "%d.%d.%d.%d:%d",
 					servers.addresses[i].ip[0], servers.addresses[i].ip[1], servers.addresses[i].ip[2],
 					servers.addresses[i].ip[3], servers.addresses[i].port);
-			}
+			}*/
 		}
 
 		if(packet->data_size >= (int)sizeof(SERVERBROWSE_INFO) &&
@@ -630,46 +791,27 @@ static void client_process_packet(NETPACKET *packet)
 			// we got ze info
 			UNPACKER up;
 			unpacker_reset(&up, (unsigned char*)packet->data+sizeof(SERVERBROWSE_INFO), packet->data_size-sizeof(SERVERBROWSE_INFO));
+			SERVER_INFO info = {0};
+
+			strncpy(info.version, unpacker_get_string(&up), 32);
+			strncpy(info.name, unpacker_get_string(&up), 64);
+			strncpy(info.map, unpacker_get_string(&up), 32);
+			info.game_type = atol(unpacker_get_string(&up));
+			info.flags = atol(unpacker_get_string(&up));
+			info.progression = atol(unpacker_get_string(&up));
+			info.num_players = atol(unpacker_get_string(&up));
+			info.max_players = atol(unpacker_get_string(&up));
 			
-			if(serverlist_lan)
-			{
-				if(servers.num != MAX_SERVERS)
-				{
-					int i = servers.num;
-					strncpy(servers.infos[i].name, unpacker_get_string(&up), 128);
-					strncpy(servers.infos[i].map, unpacker_get_string(&up), 128);
-					servers.infos[i].max_players = unpacker_get_int(&up);
-					servers.infos[i].num_players = unpacker_get_int(&up);
-					servers.infos[i].latency = 0;
-					
-					sprintf(servers.infos[i].address, "%d.%d.%d.%d:%d",
-						packet->address.ip[0], packet->address.ip[1], packet->address.ip[2],
-						packet->address.ip[3], packet->address.port);
-
-					if(config.debug)
-						dbg_msg("client", "got server info");
-					servers.num++;
-					
-				}
-			}
-			else
+			int i;
+			for(i = 0; i < info.num_players; i++)
 			{
-				int i;
-				for(i = 0; i < servers.num; i++)
-				{
-					if(net_addr4_cmp(&servers.addresses[i], &packet->address) == 0)
-					{
-						strncpy(servers.infos[i].name, unpacker_get_string(&up), 128);
-						strncpy(servers.infos[i].map, unpacker_get_string(&up), 128);
-						servers.infos[i].max_players = unpacker_get_int(&up);
-						servers.infos[i].num_players = unpacker_get_int(&up);
-						servers.infos[i].latency = ((time_get() - servers.request_times[i])*1000)/time_freq();
-						if(config.debug)
-							dbg_msg("client", "got server info");
-						break;
-					}
-				}
+				strncpy(info.player_names[i], unpacker_get_string(&up), 48);
+				info.player_scores[i] = atol(unpacker_get_string(&up));
 			}
+			
+			/* TODO: unpack players aswell */
+			client_serverbrowse_set(&packet->address, 0, &info);
+
 		}
 	}
 	else
@@ -898,8 +1040,6 @@ static void client_run(const char *direct_connect_server)
 {
 	local_start_time = time_get();
 	snapshot_part = 0;
-	info_request_begin = 0;
-	info_request_end = 0;
 	
 	client_serverbrowse_init();
 	
diff --git a/src/engine/interface.h b/src/engine/interface.h
index fb2ebe6c..118b858f 100644
--- a/src/engine/interface.h
+++ b/src/engine/interface.h
@@ -13,7 +13,7 @@ extern "C" {
 
 enum 
 {
-	MAX_CLIENTS=8,
+	MAX_CLIENTS=16,
 	SERVER_TICK_SPEED=50, /* TODO: this should be removed */
 	SNAP_CURRENT=0,
 	SNAP_PREV=1,
@@ -55,12 +55,18 @@ typedef struct
 
 typedef struct
 {
+	int progression;
+	int game_type;
 	int max_players;
 	int num_players;
+	int flags;
 	int latency; /* in ms */
-	char name[128];
-	char map[128];
-	char address[128];
+	char name[64];
+	char map[32];
+	char version[32];
+	char address[24];
+	char player_names[16][48];
+	int player_scores[16];
 } SERVER_INFO;
 
 /* image loaders */
@@ -785,7 +791,8 @@ void client_quit();
 void client_rcon(const char *cmd);
 
 void client_serverbrowse_refresh(int lan);
-int client_serverbrowse_getlist(SERVER_INFO **servers);
+SERVER_INFO *client_serverbrowse_get(int index);
+int client_serverbrowse_num();
 
 /* undocumented graphics stuff */
 void gfx_pretty_text(float x, float y, float size, const char *text, int max_width);
diff --git a/src/engine/memheap.c b/src/engine/memheap.c
new file mode 100644
index 00000000..5fe30295
--- /dev/null
+++ b/src/engine/memheap.c
@@ -0,0 +1,101 @@
+#include "system.h"
+
+typedef struct CHUNK_t
+{
+	char *memory;
+	char *current;
+	char *end;
+	struct CHUNK_t *next;
+} CHUNK;
+
+typedef struct 
+{
+	CHUNK *current;
+} HEAP;
+
+/* how large each chunk should be */
+static const int chunksize = 1024*64;
+
+/* allocates a new chunk to be used */
+static CHUNK *memheap_newchunk()
+{
+	CHUNK *chunk;
+	char *mem;
+	
+	/* allocate memory */
+	mem = mem_alloc(sizeof(CHUNK)+chunksize, 1);
+	if(!mem)
+		return 0x0;
+
+	/* the chunk structure is located in the begining of the chunk */
+	/* init it and return the chunk */
+	chunk = (CHUNK*)mem;
+	chunk->memory = (char*)(chunk+1);
+	chunk->current = chunk->memory;
+	chunk->end = chunk->memory + chunksize;
+	chunk->next = (CHUNK *)0x0;
+	return chunk;
+}
+
+/******************/
+static void *memheap_allocate_from_chunk(CHUNK *chunk, int size)
+{
+	char *mem;
+	
+	/* check if we need can fit the allocation */
+	if(chunk->current + size >= chunk->end)
+		return (void*)0x0;
+
+	/* get memory and move the pointer forward */
+	mem = chunk->current;
+	chunk->current += size;
+	return mem;
+}
+
+/* creates a heap */
+HEAP *memheap_create()
+{
+	CHUNK *chunk;
+	HEAP *heap;
+	
+	/* allocate a chunk and allocate the heap structure on that chunk */
+	chunk = memheap_newchunk();
+	heap = (HEAP *)memheap_allocate_from_chunk(chunk, sizeof(HEAP));
+	heap->current = chunk;
+	return heap;
+}
+
+/* destroys the heap */
+void memheap_destroy(HEAP *heap)
+{
+	CHUNK *chunk = heap->current;
+	CHUNK *next;
+	
+	while(chunk)
+	{
+		next = chunk->next;
+		mem_free(chunk);
+		chunk = next;
+	}
+}
+
+/* */
+void *memheap_allocate(HEAP *heap, int size)
+{
+	char *mem;
+
+	/* try to allocate from current chunk */
+	mem = (char *)memheap_allocate_from_chunk(heap->current, size);
+	if(!mem)
+	{
+		/* allocate new chunk and add it to the heap */
+		CHUNK *chunk = memheap_newchunk();
+		chunk->next = heap->current;
+		heap->current = chunk;
+		
+		/* try to allocate again */
+		mem = (char *)memheap_allocate_from_chunk(heap->current, size);
+	}
+	
+	return mem;
+}
diff --git a/src/engine/memheap.h b/src/engine/memheap.h
new file mode 100644
index 00000000..414db5e8
--- /dev/null
+++ b/src/engine/memheap.h
@@ -0,0 +1,5 @@
+
+typedef struct HEAP_t HEAP;
+HEAP *memheap_create();
+void memheap_destroy(HEAP *heap);
+void *memheap_allocate(HEAP *heap, int size);
diff --git a/src/engine/server/server.c b/src/engine/server/server.c
index db911819..3bcb79dd 100644
--- a/src/engine/server/server.c
+++ b/src/engine/server/server.c
@@ -494,7 +494,7 @@ static void server_send_serverinfo(NETADDR4 *addr)
 	packer_reset(&p);
 	packer_add_raw(&p, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO));
 	packer_add_string(&p, config.sv_name, 128);
-	packer_add_string(&p, config.sv_map, 128);
+	packer_add_string(&p, config.sv_map, 32);
 	packer_add_int(&p, netserver_max_clients(net)); /* max_players */
 	int c = 0;
 	int i;