begun the work for the new server browse backend

This commit is contained in:
Magnus Auvinen 2007-09-27 23:55:59 +00:00
parent d33bdd1dbb
commit fa05b5e2de
7 changed files with 547 additions and 78 deletions

View file

@ -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));
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);
SERVER_INFO info = {0};
if(config.debug)
dbg_msg("client", "got server info");
servers.num++;
}
}
else
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));
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();

View file

@ -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);

101
src/engine/memheap.c Normal file
View file

@ -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;
}

5
src/engine/memheap.h Normal file
View file

@ -0,0 +1,5 @@
typedef struct HEAP_t HEAP;
HEAP *memheap_create();
void memheap_destroy(HEAP *heap);
void *memheap_allocate(HEAP *heap, int size);

View file

@ -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;

View file

@ -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;

217
src/tools/fake_server.c Normal file
View file

@ -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();
}