diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-02-10 21:54:52 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-02-10 21:54:52 +0000 |
| commit | 548a919ea379a3b9d1d9e41cf4dad6b4779fd3e6 (patch) | |
| tree | 85666198fed3d4803f3ec3373c134d12bde9329b /src/engine/server | |
| parent | 2f969d9d6fece689e05857580ffb1843439e5fbb (diff) | |
| download | zcatch-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.c | 258 | ||||
| -rw-r--r-- | src/engine/server/es_server.c | 100 |
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}; |