diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-09-27 23:55:59 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-09-27 23:55:59 +0000 |
| commit | fa05b5e2de089ecd85148f3f79bafc7781142b15 (patch) | |
| tree | be3d252a8cebf175e0632dfb36dffecd88517586 | |
| parent | d33bdd1dbbf1f7ffe60fd781cde4580b5951da56 (diff) | |
| download | zcatch-fa05b5e2de089ecd85148f3f79bafc7781142b15.tar.gz zcatch-fa05b5e2de089ecd85148f3f79bafc7781142b15.zip | |
begun the work for the new server browse backend
| -rw-r--r-- | src/engine/client/client.c | 272 | ||||
| -rw-r--r-- | src/engine/interface.h | 17 | ||||
| -rw-r--r-- | src/engine/memheap.c | 101 | ||||
| -rw-r--r-- | src/engine/memheap.h | 5 | ||||
| -rw-r--r-- | src/engine/server/server.c | 2 | ||||
| -rw-r--r-- | src/game/client/menu.cpp | 11 | ||||
| -rw-r--r-- | src/tools/fake_server.c | 217 |
7 files changed, 547 insertions, 78 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; diff --git a/src/game/client/menu.cpp b/src/game/client/menu.cpp index 43b11142..a5d6d5b6 100644 --- a/src/game/client/menu.cpp +++ b/src/game/client/menu.cpp @@ -631,8 +631,7 @@ static int do_server_list(float x, float y, int *scroll_index, int *selected_ind const float real_width = item_width + 20; const float real_height = item_height * visible_items + spacing * (visible_items - 1); - SERVER_INFO *servers; - int num_servers = client_serverbrowse_getlist(&servers); + int num_servers = client_serverbrowse_num(); int r = -1; @@ -644,7 +643,7 @@ static int do_server_list(float x, float y, int *scroll_index, int *selected_ind //ui_do_image(empty_item_texture, x, y + i * item_height + i * spacing, item_width, item_height); else { - SERVER_INFO *item = &servers[item_index]; + SERVER_INFO *item = client_serverbrowse_get(item_index); bool clicked = false; clicked = ui_do_button(item, item->name, 0, x, y + i * item_height + i * spacing, item_width, item_height, @@ -718,10 +717,10 @@ static int main_render() if (last_selected_index != selected_index && selected_index != -1) { - SERVER_INFO *servers; - client_serverbrowse_getlist(&servers); + SERVER_INFO *server; + server = client_serverbrowse_get(selected_index); - strcpy(address, servers[selected_index].address); + strcpy(address, server->address); } static int refresh_button, join_button, quit_button; diff --git a/src/tools/fake_server.c b/src/tools/fake_server.c new file mode 100644 index 00000000..01ba57b0 --- /dev/null +++ b/src/tools/fake_server.c @@ -0,0 +1,217 @@ +#include <engine/config.h> +#include <engine/system.h> +#include <engine/network.h> +#include <mastersrv/mastersrv.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +/* + 32 version + 64 servername + 32 mapname + 2 gametype + 2 flags + 4 progression + 3 num players + 3 max players + { + 48 name + 6 score + } * players + + 111111111122222222223333333333444444444 +123456789012345678901234567890123456789012345678 +0.3 2d82e361de24cb25 +my own private little server +magnus.auvinen@teewars.somehost-strage-host.com +*/ + +NETSERVER *net; + +int progression = 50; +int game_type = 0; +int flags = 0; + +const char *version = "0.3.0 2d82e361de24cb25"; +const char *map = "somemap"; +const char *server_name = "unnamed server"; +NETADDR4 master_servers[16] = {{{0},0}}; +int num_masters = 0; + +const char *player_names[16] = {0}; +int player_scores[16] = {0}; +int num_players = 0; +int max_players = 0; + +static void send_heartbeats() +{ + int i = 0; + + NETPACKET p; + p.client_id = -1; + p.flags = PACKETFLAG_CONNLESS; + p.data_size = sizeof(SERVERBROWSE_HEARTBEAT); + p.data = SERVERBROWSE_HEARTBEAT; + + for(i = 0; i < num_masters; i++) + { + p.address = master_servers[i]; + netserver_send(net, &p); + } +} + +char infomsg[1024]; +int infomsg_size; + +static void writestr(const char *str) +{ + int l = strlen(str)+1; + memcpy(&infomsg[infomsg_size], str, l); + infomsg_size += l; +} + +static void writeint(int i) +{ + char buf[64]; + sprintf(buf, "%d", i); + writestr(buf); +} + +static void build_infomessage() +{ + int i; + infomsg_size = sizeof(SERVERBROWSE_INFO); + memcpy(infomsg, SERVERBROWSE_INFO, infomsg_size); + + writestr(version); + writestr(server_name); + writestr(map); + writeint(game_type); + writeint(flags); + writeint(progression); + writeint(num_players); + writeint(max_players); + for(i = 0; i < num_players; i++) + { + writestr(player_names[i]); + writeint(player_scores[i]); + } +} + +static void send_serverinfo(NETADDR4 *addr) +{ + NETPACKET p; + p.client_id = -1; + p.address = *addr; + p.flags = PACKETFLAG_CONNLESS; + p.data_size = infomsg_size; + p.data = infomsg; + netserver_send(net, &p); +} + +static void send_fwcheckresponse(NETADDR4 *addr) +{ + NETPACKET p; + p.client_id = -1; + p.address = *addr; + p.flags = PACKETFLAG_CONNLESS; + p.data_size = sizeof(SERVERBROWSE_FWRESPONSE); + p.data = SERVERBROWSE_FWRESPONSE; + netserver_send(net, &p); +} + +static int run() +{ + int64 next_heartbeat = 0; + NETADDR4 bindaddr = {{0},0}; + net = netserver_open(bindaddr, 0, 0); + if(!net) + return -1; + + while(1) + { + NETPACKET p; + netserver_update(net); + while(netserver_recv(net, &p)) + { + if(p.client_id == -1) + { + if(p.data_size == sizeof(SERVERBROWSE_GETINFO) && + memcmp(p.data, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0) + { + send_serverinfo(&p.address); + } + else if(p.data_size == sizeof(SERVERBROWSE_FWCHECK) && + memcmp(p.data, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0) + { + send_fwcheckresponse(&p.address); + } + } + } + + /* send heartbeats if needed */ + if(next_heartbeat < time_get()) + { + next_heartbeat = time_get()+time_freq()*30; + send_heartbeats(); + } + + thread_sleep(10); + } +} + +int main(int argc, char **argv) +{ + net_init(); + + while(argc) + { + if(strcmp(*argv, "-m") == 0) + { + argc--; argv++; + net_host_lookup(*argv, 0, &master_servers[num_masters]); + argc--; argv++; + master_servers[num_masters].port = atoi(*argv); + num_masters++; + } + else if(strcmp(*argv, "-p") == 0) + { + argc--; argv++; + player_names[num_players++] = *argv; + argc--; argv++; + player_scores[num_players] = atoi(*argv); + } + else if(strcmp(*argv, "-x") == 0) + { + argc--; argv++; + max_players = atoi(*argv); + } + else if(strcmp(*argv, "-t") == 0) + { + argc--; argv++; + game_type = atoi(*argv); + } + else if(strcmp(*argv, "-p") == 0) + { + argc--; argv++; + progression = atoi(*argv); + } + else if(strcmp(*argv, "-f") == 0) + { + argc--; argv++; + flags = atoi(*argv); + } + else if(strcmp(*argv, "-n") == 0) + { + argc--; argv++; + server_name = *argv; + } + + argc--; argv++; + } + + build_infomessage(); + return run(); +} + |