mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
merged 0.3.4 changes to trunk
This commit is contained in:
parent
2f969d9d6f
commit
548a919ea3
|
@ -1098,12 +1098,36 @@ static void client_update()
|
|||
}
|
||||
|
||||
/* STRESS TEST: join the server again */
|
||||
if(client_state() == CLIENTSTATE_OFFLINE && config.dbg_stress && (frames%100) == 0)
|
||||
client_connect(config.dbg_stress_server);
|
||||
if(config.dbg_stress)
|
||||
{
|
||||
static int64 action_taken = 0;
|
||||
int64 now = time_get();
|
||||
if(client_state() == CLIENTSTATE_OFFLINE)
|
||||
{
|
||||
if(now > action_taken+time_freq()*2)
|
||||
{
|
||||
dbg_msg("stress", "reconnecting!");
|
||||
client_connect(config.dbg_stress_server);
|
||||
action_taken = now;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(now > action_taken+time_freq()*(10+config.dbg_stress))
|
||||
{
|
||||
dbg_msg("stress", "disconnecting!");
|
||||
client_disconnect();
|
||||
action_taken = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* pump the network */
|
||||
client_pump_network();
|
||||
|
||||
/* update the maser server registry */
|
||||
mastersrv_update();
|
||||
|
||||
/* update the server browser */
|
||||
client_serverbrowse_update();
|
||||
}
|
||||
|
@ -1128,12 +1152,15 @@ static void client_run()
|
|||
if(!gfx_init())
|
||||
return;
|
||||
|
||||
/* start refreshing addresses while we load */
|
||||
mastersrv_refresh_addresses();
|
||||
|
||||
/* init the editor */
|
||||
editor_init();
|
||||
|
||||
/* sound is allowed to fail */
|
||||
snd_init();
|
||||
|
||||
|
||||
/* load data */
|
||||
if(!client_load_data())
|
||||
return;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <engine/e_client_interface.h>
|
||||
#include <engine/e_config.h>
|
||||
#include <engine/e_memheap.h>
|
||||
#include <engine/e_engine.h>
|
||||
|
||||
#include <mastersrv/mastersrv.h>
|
||||
|
||||
|
@ -341,18 +342,27 @@ void client_serverbrowse_refresh(int lan)
|
|||
}
|
||||
else
|
||||
{
|
||||
NETADDR4 master_server;
|
||||
NETADDR4 addr;
|
||||
NETPACKET p;
|
||||
|
||||
net_host_lookup(config.masterserver, MASTERSERVER_PORT, &master_server);
|
||||
int i;
|
||||
|
||||
/*net_host_lookup(config.masterserver, MASTERSERVER_PORT, &master_server);*/
|
||||
|
||||
mem_zero(&p, sizeof(p));
|
||||
p.client_id = -1;
|
||||
p.address = master_server;
|
||||
p.flags = PACKETFLAG_CONNLESS;
|
||||
p.data_size = sizeof(SERVERBROWSE_GETLIST);
|
||||
p.data = SERVERBROWSE_GETLIST;
|
||||
netclient_send(net, &p);
|
||||
|
||||
for(i = 0; i < MAX_MASTERSERVERS; i++)
|
||||
{
|
||||
addr = mastersrv_get(i);
|
||||
if(!addr.ip[0] && !addr.ip[1] && !addr.ip[2] && !addr.ip[3])
|
||||
continue;
|
||||
|
||||
p.address = addr;
|
||||
netclient_send(net, &p);
|
||||
}
|
||||
|
||||
if(config.debug)
|
||||
dbg_msg("client", "requesting server list");
|
||||
|
|
|
@ -6,77 +6,7 @@
|
|||
|
||||
#include "e_system.h"
|
||||
#include "e_config.h"
|
||||
|
||||
/* buffered stream for reading lines, should perhaps be something smaller */
|
||||
typedef struct
|
||||
{
|
||||
char buffer[4*1024];
|
||||
unsigned buffer_pos;
|
||||
unsigned buffer_size;
|
||||
unsigned buffer_max_size;
|
||||
IOHANDLE io;
|
||||
} LINEREADER;
|
||||
|
||||
void linereader_init(LINEREADER *lr, IOHANDLE io)
|
||||
{
|
||||
lr->buffer_max_size = 4*1024;
|
||||
lr->buffer_size = 0;
|
||||
lr->buffer_pos = 0;
|
||||
lr->io = io;
|
||||
}
|
||||
|
||||
char *linereader_get(LINEREADER *lr)
|
||||
{
|
||||
unsigned line_start = lr->buffer_pos;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(lr->buffer_pos >= lr->buffer_size)
|
||||
{
|
||||
/* fetch more */
|
||||
|
||||
/* move the remaining part to the front */
|
||||
unsigned read;
|
||||
unsigned left = lr->buffer_size - line_start;
|
||||
|
||||
if(line_start > lr->buffer_size)
|
||||
left = 0;
|
||||
if(left)
|
||||
mem_move(lr->buffer, &lr->buffer[line_start], left);
|
||||
lr->buffer_pos = left;
|
||||
|
||||
/* fill the buffer */
|
||||
read = io_read(lr->io, &lr->buffer[lr->buffer_pos], lr->buffer_max_size-lr->buffer_pos);
|
||||
lr->buffer_size = left + read;
|
||||
line_start = 0;
|
||||
|
||||
if(!read)
|
||||
{
|
||||
if(left)
|
||||
{
|
||||
lr->buffer[left] = 0; /* return the last line */
|
||||
lr->buffer_pos = left;
|
||||
lr->buffer_size = left;
|
||||
return lr->buffer;
|
||||
}
|
||||
else
|
||||
return 0x0; /* we are done! */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lr->buffer[lr->buffer_pos] == '\n' || lr->buffer[lr->buffer_pos] == '\r')
|
||||
{
|
||||
/* line found */
|
||||
lr->buffer[lr->buffer_pos] = 0;
|
||||
lr->buffer_pos++;
|
||||
return &lr->buffer[line_start];
|
||||
}
|
||||
else
|
||||
lr->buffer_pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "e_linereader.h"
|
||||
|
||||
CONFIGURATION config;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ MACRO_CONFIG_INT(gfx_debug_resizable, 0, 0, 0)
|
|||
MACRO_CONFIG_INT(key_screenshot, 267, 32, 512)
|
||||
MACRO_CONFIG_INT(inp_mousesens, 100, 5, 100000)
|
||||
|
||||
MACRO_CONFIG_STR(masterserver, 128, "master.teewars.com")
|
||||
/*MACRO_CONFIG_STR(masterserver, 128, "master.teewars.com")*/
|
||||
|
||||
MACRO_CONFIG_STR(sv_name, 128, "unnamed server")
|
||||
MACRO_CONFIG_STR(sv_bindaddr, 128, "")
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
/*#include <engine/e_client_interface.h>*/
|
||||
#include <engine/e_config.h>
|
||||
#include <engine/e_console.h>
|
||||
|
||||
#include <engine/e_engine.h>
|
||||
#include "e_linereader.h"
|
||||
|
||||
static void con_dbg_dumpmem(void *result, void *user_data)
|
||||
{
|
||||
|
@ -24,7 +25,7 @@ const char *engine_savepath(const char *filename, char *buffer, int max)
|
|||
}
|
||||
|
||||
|
||||
void engine_init(const char *appname, int argc, char **argv)
|
||||
void engine_init(const char *appname)
|
||||
{
|
||||
dbg_msg("engine", "running on %s-%s-%s", CONF_FAMILY_STRING, CONF_PLATFORM_STRING, CONF_ARCH_STRING);
|
||||
#ifdef CONF_ARCH_ENDIAN_LITTLE
|
||||
|
@ -37,7 +38,7 @@ void engine_init(const char *appname, int argc, char **argv)
|
|||
|
||||
/* init the network */
|
||||
net_init();
|
||||
|
||||
|
||||
/* create storage location */
|
||||
{
|
||||
char path[1024] = {0};
|
||||
|
@ -92,6 +93,10 @@ void engine_parse_arguments(int argc, char **argv)
|
|||
for(i = 1; i < argc; i++)
|
||||
config_set(argv[i]);
|
||||
}
|
||||
|
||||
/* set default servers and load from disk*/
|
||||
mastersrv_default();
|
||||
mastersrv_load();
|
||||
}
|
||||
|
||||
void engine_writeconfig()
|
||||
|
@ -175,3 +180,207 @@ void perf_dump(PERFORMACE_INFO *top)
|
|||
{
|
||||
perf_dump_imp(top, 0);
|
||||
}
|
||||
|
||||
/* master server functions */
|
||||
enum
|
||||
{
|
||||
NUM_LOOKUP_THREADS=4,
|
||||
|
||||
STATE_PROCESSED=0,
|
||||
STATE_RESULT,
|
||||
STATE_QUERYING
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char hostname[128];
|
||||
NETADDR4 addr;
|
||||
|
||||
/* these are used for lookups */
|
||||
struct {
|
||||
NETADDR4 addr;
|
||||
int result;
|
||||
void *thread;
|
||||
volatile int state;
|
||||
} lookup;
|
||||
} MASTER_INFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int start;
|
||||
int num;
|
||||
} THREAD_INFO;
|
||||
|
||||
static MASTER_INFO master_servers[MAX_MASTERSERVERS] = {{{0}}};
|
||||
static THREAD_INFO thread_info[NUM_LOOKUP_THREADS];
|
||||
static int needs_update = 0;
|
||||
|
||||
void lookup_thread(void *user)
|
||||
{
|
||||
THREAD_INFO *info = (THREAD_INFO *)user;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < info->num; i++)
|
||||
{
|
||||
int index = info->start+i;
|
||||
master_servers[index].lookup.result = net_host_lookup(master_servers[index].hostname, 8300, &master_servers[index].lookup.addr);
|
||||
master_servers[index].lookup.state = STATE_RESULT;
|
||||
}
|
||||
}
|
||||
|
||||
int mastersrv_refresh_addresses()
|
||||
{
|
||||
int i;
|
||||
dbg_msg("engine/mastersrv", "refreshing master server addresses");
|
||||
|
||||
/* spawn threads that does the lookups */
|
||||
for(i = 0; i < NUM_LOOKUP_THREADS; i++)
|
||||
{
|
||||
thread_info[i].start = MAX_MASTERSERVERS/NUM_LOOKUP_THREADS * i;
|
||||
thread_info[i].num = MAX_MASTERSERVERS/NUM_LOOKUP_THREADS;
|
||||
master_servers[i].lookup.state = STATE_QUERYING;
|
||||
master_servers[i].lookup.thread = thread_create(lookup_thread, &thread_info[i]);
|
||||
}
|
||||
|
||||
needs_update = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mastersrv_update()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* check if we need to update */
|
||||
if(!needs_update)
|
||||
return;
|
||||
needs_update = 0;
|
||||
|
||||
for(i = 0; i < MAX_MASTERSERVERS; i++)
|
||||
{
|
||||
if(master_servers[i].lookup.state == STATE_RESULT)
|
||||
{
|
||||
/* we got a result from the lookup ready */
|
||||
if(master_servers[i].lookup.result == 0)
|
||||
master_servers[i].addr = master_servers[i].lookup.addr;
|
||||
master_servers[i].lookup.state = STATE_PROCESSED;
|
||||
}
|
||||
|
||||
/* set the needs_update flag if we isn't done */
|
||||
if(master_servers[i].lookup.state != STATE_PROCESSED)
|
||||
needs_update = 1;
|
||||
}
|
||||
|
||||
if(!needs_update)
|
||||
{
|
||||
dbg_msg("engine/mastersrv", "saving addresses");
|
||||
mastersrv_save();
|
||||
}
|
||||
}
|
||||
|
||||
int mastersrv_refreshing()
|
||||
{
|
||||
return needs_update;
|
||||
}
|
||||
|
||||
NETADDR4 mastersrv_get(int index)
|
||||
{
|
||||
return master_servers[index].addr;
|
||||
}
|
||||
|
||||
const char *mastersrv_name(int index)
|
||||
{
|
||||
return master_servers[index].hostname;
|
||||
}
|
||||
|
||||
void mastersrv_dump_servers()
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < MAX_MASTERSERVERS; i++)
|
||||
{
|
||||
dbg_msg("mastersrv", "#%d = %d.%d.%d.%d", i,
|
||||
master_servers[i].addr.ip[0], master_servers[i].addr.ip[1],
|
||||
master_servers[i].addr.ip[2], master_servers[i].addr.ip[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void mastersrv_default()
|
||||
{
|
||||
int i;
|
||||
mem_zero(master_servers, sizeof(master_servers));
|
||||
for(i = 0; i < MAX_MASTERSERVERS; i++)
|
||||
sprintf(master_servers[i].hostname, "master%d.teewars.com", i+1);
|
||||
}
|
||||
|
||||
int mastersrv_load()
|
||||
{
|
||||
LINEREADER lr;
|
||||
IOHANDLE file;
|
||||
int count = 0;
|
||||
char filename[1024];
|
||||
|
||||
engine_savepath("masters.cfg", filename, sizeof(filename));
|
||||
|
||||
/* try to open file */
|
||||
file = io_open(filename, IOFLAG_READ);
|
||||
if(!file)
|
||||
return -1;
|
||||
|
||||
linereader_init(&lr, file);
|
||||
while(1)
|
||||
{
|
||||
MASTER_INFO info = {{0}};
|
||||
int ip[4];
|
||||
const char *line = linereader_get(&lr);
|
||||
if(!line)
|
||||
break;
|
||||
|
||||
/* parse line */
|
||||
if(sscanf(line, "%s %d.%d.%d.%d", info.hostname, &ip[0], &ip[1], &ip[2], &ip[3]) == 5)
|
||||
{
|
||||
info.addr.ip[0] = (unsigned char)ip[0];
|
||||
info.addr.ip[1] = (unsigned char)ip[1];
|
||||
info.addr.ip[2] = (unsigned char)ip[2];
|
||||
info.addr.ip[3] = (unsigned char)ip[3];
|
||||
info.addr.port = 8300;
|
||||
if(count != MAX_MASTERSERVERS)
|
||||
{
|
||||
master_servers[count] = info;
|
||||
count++;
|
||||
}
|
||||
else
|
||||
dbg_msg("engine/mastersrv", "warning: skipped master server '%s' due to limit of %d", line, MAX_MASTERSERVERS);
|
||||
}
|
||||
else
|
||||
dbg_msg("engine/mastersrv", "warning: couldn't parse master server '%s'", line);
|
||||
}
|
||||
|
||||
io_close(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mastersrv_save()
|
||||
{
|
||||
IOHANDLE file;
|
||||
int i;
|
||||
char filename[1024];
|
||||
|
||||
engine_savepath("masters.cfg", filename, sizeof(filename));
|
||||
|
||||
/* try to open file */
|
||||
file = io_open(filename, IOFLAG_WRITE);
|
||||
if(!file)
|
||||
return -1;
|
||||
|
||||
for(i = 0; i < MAX_MASTERSERVERS; i++)
|
||||
{
|
||||
char buf[1024];
|
||||
sprintf(buf, "%s %d.%d.%d.%d\n", master_servers[i].hostname,
|
||||
master_servers[i].addr.ip[0], master_servers[i].addr.ip[1],
|
||||
master_servers[i].addr.ip[2], master_servers[i].addr.ip[3]);
|
||||
|
||||
io_write(file, buf, strlen(buf));
|
||||
}
|
||||
|
||||
io_close(file);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -4,3 +4,20 @@ const char *engine_savepath(const char *filename, char *buffer, int max);
|
|||
void engine_init(const char *appname);
|
||||
void engine_parse_arguments(int argc, char **argv);
|
||||
void engine_writeconfig();
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_MASTERSERVERS=16
|
||||
};
|
||||
|
||||
void mastersrv_default();
|
||||
int mastersrv_load();
|
||||
int mastersrv_save();
|
||||
|
||||
int mastersrv_refresh_addresses();
|
||||
void mastersrv_update();
|
||||
int mastersrv_refreshing();
|
||||
void mastersrv_dump_servers();
|
||||
NETADDR4 mastersrv_get(int index);
|
||||
const char *mastersrv_name(int index);
|
||||
|
|
62
src/engine/e_linereader.c
Normal file
62
src/engine/e_linereader.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "e_linereader.h"
|
||||
|
||||
void linereader_init(LINEREADER *lr, IOHANDLE io)
|
||||
{
|
||||
lr->buffer_max_size = 4*1024;
|
||||
lr->buffer_size = 0;
|
||||
lr->buffer_pos = 0;
|
||||
lr->io = io;
|
||||
}
|
||||
|
||||
char *linereader_get(LINEREADER *lr)
|
||||
{
|
||||
unsigned line_start = lr->buffer_pos;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(lr->buffer_pos >= lr->buffer_size)
|
||||
{
|
||||
/* fetch more */
|
||||
|
||||
/* move the remaining part to the front */
|
||||
unsigned read;
|
||||
unsigned left = lr->buffer_size - line_start;
|
||||
|
||||
if(line_start > lr->buffer_size)
|
||||
left = 0;
|
||||
if(left)
|
||||
mem_move(lr->buffer, &lr->buffer[line_start], left);
|
||||
lr->buffer_pos = left;
|
||||
|
||||
/* fill the buffer */
|
||||
read = io_read(lr->io, &lr->buffer[lr->buffer_pos], lr->buffer_max_size-lr->buffer_pos);
|
||||
lr->buffer_size = left + read;
|
||||
line_start = 0;
|
||||
|
||||
if(!read)
|
||||
{
|
||||
if(left)
|
||||
{
|
||||
lr->buffer[left] = 0; /* return the last line */
|
||||
lr->buffer_pos = left;
|
||||
lr->buffer_size = left;
|
||||
return lr->buffer;
|
||||
}
|
||||
else
|
||||
return 0x0; /* we are done! */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lr->buffer[lr->buffer_pos] == '\n' || lr->buffer[lr->buffer_pos] == '\r')
|
||||
{
|
||||
/* line found */
|
||||
lr->buffer[lr->buffer_pos] = 0;
|
||||
lr->buffer_pos++;
|
||||
return &lr->buffer[line_start];
|
||||
}
|
||||
else
|
||||
lr->buffer_pos++;
|
||||
}
|
||||
}
|
||||
}
|
14
src/engine/e_linereader.h
Normal file
14
src/engine/e_linereader.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "e_system.h"
|
||||
|
||||
/* buffered stream for reading lines, should perhaps be something smaller */
|
||||
typedef struct
|
||||
{
|
||||
char buffer[4*1024];
|
||||
unsigned buffer_pos;
|
||||
unsigned buffer_size;
|
||||
unsigned buffer_max_size;
|
||||
IOHANDLE io;
|
||||
} LINEREADER;
|
||||
|
||||
void linereader_init(LINEREADER *lr, IOHANDLE io);
|
||||
char *linereader_get(LINEREADER *lr);
|
|
@ -268,6 +268,45 @@ int io_close(IOHANDLE io)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void *thread_create(void (*threadfunc)(void *), void *u)
|
||||
{
|
||||
#if defined(CONF_FAMILY_UNIX)
|
||||
pthread_t id;
|
||||
pthread_create(&id, NULL, (void *(*)(void*))threadfunc, u);
|
||||
return (void*)id;
|
||||
#elif defined(CONF_FAMILY_WINDOWS)
|
||||
return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc, u, 0, NULL);
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
}
|
||||
|
||||
void thread_wait(void *thread)
|
||||
{
|
||||
#if defined(CONF_FAMILY_UNIX)
|
||||
pthread_join((pthread_t)thread, NULL);
|
||||
#elif defined(CONF_FAMILY_WINDOWS)
|
||||
WaitForSingleObject((HANDLE)thread, INFINITE);
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
}
|
||||
|
||||
void thread_destroy(void *thread)
|
||||
{
|
||||
}
|
||||
|
||||
void thread_yield()
|
||||
{
|
||||
#if defined(CONF_FAMILY_UNIX)
|
||||
sched_yield();
|
||||
#elif defined(CONF_FAMILY_WINDOWS)
|
||||
Sleep(0);
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
}
|
||||
|
||||
void thread_sleep(int milliseconds)
|
||||
{
|
||||
#if defined(CONF_FAMILY_UNIX)
|
||||
|
@ -279,6 +318,9 @@ void thread_sleep(int milliseconds)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(CONF_FAMILY_UNIX)
|
||||
typedef pthread_mutex_t LOCKINTERNAL;
|
||||
#elif defined(CONF_FAMILY_WINDOWS)
|
||||
|
@ -757,6 +799,11 @@ int net_socket_read_wait(NETSOCKET sock, int time)
|
|||
#endif*/
|
||||
}
|
||||
|
||||
unsigned time_timestamp()
|
||||
{
|
||||
return time(0);
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -268,13 +268,6 @@ int io_close(IOHANDLE io);
|
|||
|
||||
/**** Group: Threads ****/
|
||||
|
||||
int thread_create(); /* NOT IMPLEMENTED */
|
||||
int thread_destory(); /* NOT IMPLEMENTED */
|
||||
|
||||
int thread_run(); /* NOT IMPLEMENTED */
|
||||
int thread_pause(); /* NOT IMPLEMENTED */
|
||||
int thread_wait(); /* NOT IMPLEMENTED */
|
||||
|
||||
/*****
|
||||
Function: thread_sleep
|
||||
|
||||
|
@ -517,6 +510,12 @@ int net_socket_read_wait(NETSOCKET sock, int time);
|
|||
void mem_debug_dump();
|
||||
int mem_allocated();
|
||||
|
||||
void *thread_create(void (*threadfunc)(void *), void *user);
|
||||
void thread_wait(void *thread);
|
||||
void thread_destroy(void *thread);
|
||||
void thread_yield();
|
||||
unsigned time_timestamp();
|
||||
|
||||
void swap_endian(void *data, unsigned elem_size, unsigned num);
|
||||
|
||||
/* #define cache_prefetch(addr) __builtin_prefetch(addr) */
|
||||
|
|
258
src/engine/server/es_register.c
Normal file
258
src/engine/server/es_register.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
if(!register_process_packet(&packet))
|
||||
{
|
||||
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 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};
|
||||
|
|
|
@ -576,6 +576,7 @@ player::player()
|
|||
void player::init()
|
||||
{
|
||||
proximity_radius = phys_size;
|
||||
dbg_msg("", "%p %d -> %d (init)", this, client_id, -1);
|
||||
client_id = -1;
|
||||
team = -1; // -1 == spectator
|
||||
|
||||
|
@ -2116,6 +2117,7 @@ void mods_client_enter(int client_id)
|
|||
void mods_connected(int client_id)
|
||||
{
|
||||
players[client_id].init();
|
||||
dbg_msg("", "%p %d -> %d (mods_connected)", &players[client_id], players[client_id].client_id, client_id);
|
||||
players[client_id].client_id = client_id;
|
||||
|
||||
//dbg_msg("game", "connected player='%d:%s'", client_id, server_clientname(client_id));
|
||||
|
@ -2144,6 +2146,7 @@ void mods_client_drop(int client_id)
|
|||
gameobj->on_player_death(&players[client_id], 0, -1);
|
||||
world->remove_entity(&players[client_id]);
|
||||
world->core.players[client_id] = 0x0;
|
||||
dbg_msg("", "%p %d -> %d (mods_client_drop)", &players[client_id], players[client_id].client_id, -1);
|
||||
players[client_id].client_id = -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,14 @@ static struct packet_data
|
|||
unsigned char header[sizeof(SERVERBROWSE_LIST)];
|
||||
NETADDR4 servers[MAX_SERVERS];
|
||||
} data;
|
||||
|
||||
static struct count_packet_data
|
||||
{
|
||||
unsigned char header[sizeof(SERVERBROWSE_COUNT)];
|
||||
unsigned char high;
|
||||
unsigned char low;
|
||||
} count_data;
|
||||
|
||||
static int64 server_expire[MAX_SERVERS];
|
||||
static int num_servers = 0;
|
||||
|
||||
|
@ -41,6 +49,9 @@ void send_ok(NETADDR4 *addr)
|
|||
p.flags = PACKETFLAG_CONNLESS;
|
||||
p.data_size = sizeof(SERVERBROWSE_FWOK);
|
||||
p.data = SERVERBROWSE_FWOK;
|
||||
|
||||
// send on both to be sure
|
||||
net_checker.send(&p);
|
||||
net_op.send(&p);
|
||||
}
|
||||
|
||||
|
@ -183,6 +194,8 @@ int main(int argc, char **argv)
|
|||
// TODO: check socket for errors
|
||||
|
||||
mem_copy(data.header, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST));
|
||||
mem_copy(count_data.header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT));
|
||||
|
||||
dbg_msg("mastersrv", "started");
|
||||
|
||||
while(1)
|
||||
|
@ -207,6 +220,21 @@ int main(int argc, char **argv)
|
|||
// add it
|
||||
add_checkserver(&packet.address, &alt);
|
||||
}
|
||||
else if(packet.data_size == sizeof(SERVERBROWSE_GETCOUNT) &&
|
||||
memcmp(packet.data, SERVERBROWSE_GETCOUNT, sizeof(SERVERBROWSE_GETCOUNT)) == 0)
|
||||
{
|
||||
dbg_msg("mastersrv", "count requested, responding with %d", num_servers);
|
||||
|
||||
NETPACKET p;
|
||||
p.client_id = -1;
|
||||
p.address = packet.address;
|
||||
p.flags = PACKETFLAG_CONNLESS;
|
||||
p.data_size = sizeof(count_data);
|
||||
p.data = &count_data;
|
||||
count_data.high = (num_servers>>8)&0xff;
|
||||
count_data.low = num_servers&0xff;
|
||||
net_op.send(&p);
|
||||
}
|
||||
else if(packet.data_size == sizeof(SERVERBROWSE_GETLIST) &&
|
||||
memcmp(packet.data, SERVERBROWSE_GETLIST, sizeof(SERVERBROWSE_GETLIST)) == 0)
|
||||
{
|
||||
|
|
|
@ -10,6 +10,9 @@ static const unsigned char SERVERBROWSE_HEARTBEAT[] = {255, 255, 255, 255, 'b',
|
|||
static const unsigned char SERVERBROWSE_GETLIST[] = {255, 255, 255, 255, 'r', 'e', 'q', 't'};
|
||||
static const unsigned char SERVERBROWSE_LIST[] = {255, 255, 255, 255, 'l', 'i', 's', 't'};
|
||||
|
||||
static const unsigned char SERVERBROWSE_GETCOUNT[] = {255, 255, 255, 255, 'c', 'o', 'u', 'n'};
|
||||
static const unsigned char SERVERBROWSE_COUNT[] = {255, 255, 255, 255, 's', 'i', 'z', 'e'};
|
||||
|
||||
static const unsigned char SERVERBROWSE_GETINFO[] = {255, 255, 255, 255, 'g', 'i', 'e', 'f'};
|
||||
static const unsigned char SERVERBROWSE_INFO[] = {255, 255, 255, 255, 'i', 'n', 'f', 'o'};
|
||||
|
||||
|
|
|
@ -45,20 +45,29 @@ 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;
|
||||
static unsigned char data[sizeof(SERVERBROWSE_HEARTBEAT) + 2];
|
||||
NETPACKET packet;
|
||||
int i;
|
||||
|
||||
mem_copy(data, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT));
|
||||
|
||||
packet.client_id = -1;
|
||||
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 */
|
||||
data[sizeof(SERVERBROWSE_HEARTBEAT)] = 0;
|
||||
data[sizeof(SERVERBROWSE_HEARTBEAT)+1] = 0;
|
||||
|
||||
for(i = 0; i < num_masters; i++)
|
||||
{
|
||||
p.address = master_servers[i];
|
||||
netserver_send(net, &p);
|
||||
packet.address = master_servers[i];
|
||||
netserver_send(net, &packet);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue