diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-07-21 18:07:27 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-07-21 18:07:27 +0000 |
| commit | 9e4aea97bdb5a903150df57f8d546733ce4b4db2 (patch) | |
| tree | 7e18776bd7ace981895bca01ac753c9c289a71a5 /src/engine | |
| parent | f0e8502050ce27b9cef72fa385619d13faa35c27 (diff) | |
| download | zcatch-9e4aea97bdb5a903150df57f8d546733ce4b4db2.tar.gz zcatch-9e4aea97bdb5a903150df57f8d546733ce4b4db2.zip | |
lots of cool new features :D new master server
Diffstat (limited to 'src/engine')
| -rw-r--r-- | src/engine/client/client.cpp | 481 | ||||
| -rw-r--r-- | src/engine/interface.h | 16 | ||||
| -rw-r--r-- | src/engine/network.cpp | 209 | ||||
| -rw-r--r-- | src/engine/network.h | 5 | ||||
| -rw-r--r-- | src/engine/server/server.cpp | 101 |
5 files changed, 505 insertions, 307 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 57b3bd57..816a30e7 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -20,6 +20,8 @@ #include <engine/config.h> #include <engine/network.h> +#include <mastersrv/mastersrv.h> + using namespace baselib; // --- input wrappers --- @@ -156,15 +158,92 @@ int client_send_msg() return 0; } +static struct +{ + server_info infos[MAX_SERVERS]; + int64 request_times[MAX_SERVERS]; + netaddr4 addresses[MAX_SERVERS]; + int num; +} servers; + +static netaddr4 master_server; + +int client_serverbrowse_getlist(server_info **serverlist) +{ + *serverlist = servers.infos; + return servers.num; +} + +void client_serverbrowse_refresh() +{ + dbg_msg("client", "requesting server list"); + NETPACKET packet; + packet.client_id = -1; + packet.address = master_server; + packet.flags = PACKETFLAG_CONNLESS; + packet.data_size = sizeof(SERVERBROWSE_GETLIST); + packet.data = SERVERBROWSE_GETLIST; + net.send(&packet); + + // reset the list + servers.num = 0; +} + +enum +{ + STATE_OFFLINE, + STATE_CONNECTING, + STATE_LOADING, + STATE_ONLINE, + STATE_BROKEN, + STATE_QUIT, +}; + +static netaddr4 server_address; + +static int state; +static int get_state() { return state; } +static void set_state(int s) +{ + dbg_msg("game", "state change. last=%d current=%d", state, s); + state = s; +} + + +void client_connect(const char *server_address_str) +{ + char buf[512]; + strncpy(buf, server_address_str, 512); + + const char *port_str = 0; + for(int k = 0; buf[k]; k++) + { + if(buf[k] == ':') + { + port_str = &(buf[k+1]); + buf[k] = 0; + break; + } + } + + int port = 8303; + if(port_str) + port = atoi(port_str); + + if(net_host_lookup(buf, port, &server_address) != 0) + dbg_msg("client", "could not find the address of %s, connecting to localhost", buf); + + net.connect(&server_address); + set_state(STATE_CONNECTING); +} + // --- client --- // TODO: remove this class class client { public: - - //socket_udp4 socket; - //connection conn; - int64 reconnect_timer; + int info_request_begin; + int info_request_end; int snapshot_part; @@ -173,24 +252,6 @@ public: // data to hold three snapshots // previous, - enum - { - STATE_OFFLINE, - STATE_CONNECTING, - STATE_LOADING, - STATE_ONLINE, - STATE_BROKEN, - STATE_QUIT, - }; - - int state; - int get_state() { return state; } - void set_state(int s) - { - dbg_msg("game", "state change. last=%d current=%d", state, s); - state = s; - } - void send_info() { recived_snapshots = 0; @@ -242,12 +303,6 @@ public: map_unload(); } - void connect(netaddr4 *server_address) - { - net.connect(server_address); - set_state(STATE_CONNECTING); - } - bool load_data() { debug_font = gfx_load_texture("data/debug_font.png"); @@ -293,13 +348,11 @@ public: } else if (get_state() != STATE_CONNECTING && get_state() != STATE_LOADING) { - netaddr4 server_address; - int status = modmenu_render(&server_address); + //netaddr4 server_address; + int status = modmenu_render(); if (status == -1) set_state(STATE_QUIT); - else if (status) - connect(&server_address); } else if (get_state() == STATE_CONNECTING || get_state() == STATE_LOADING) { @@ -332,7 +385,7 @@ public: } } - void run(netaddr4 *server_address) + void run(const char *direct_connect_server) { local_start_time = time_get(); snapshot_part = 0; @@ -356,20 +409,16 @@ public: // init menu modmenu_init(); - net.open(0); - // open socket - /* - if(!socket.open(0)) - { - dbg_msg("network/client", "failed to open socket"); - return; - }*/ + net.open(0, 0); + + // + net_host_lookup(MASTERSERVER_ADDRESS, MASTERSERVER_PORT, &master_server); // connect to the server if wanted - if(server_address) - connect(server_address); - + if(direct_connect_server) + client_connect(direct_connect_server); + //int64 inputs_per_second = 50; //int64 time_per_input = time_freq()/inputs_per_second; int64 game_starttime = time_get(); @@ -413,6 +462,9 @@ public: // pump the network pump_network(); + // update the server browser + serverbrowse_update(); + // render render(); @@ -457,146 +509,235 @@ public: send_error(msg); set_state(STATE_BROKEN); } + + void serverbrowse_request(int id) + { + 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); + 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; + net.send(&packet); + servers.request_times[id] = time_get(); + } + + void serverbrowse_update() + { + int64 timeout = time_freq(); + int64 now = time_get(); + int max_requests = 10; + + // timeout old requests + while(info_request_begin < servers.num && info_request_begin < info_request_end) + { + if(now > servers.request_times[info_request_begin]+timeout) + info_request_begin++; + else + break; + } + + // send new requests + while(info_request_end < servers.num && info_request_end-info_request_begin < max_requests) + { + serverbrowse_request(info_request_end); + info_request_end++; + } + } void process_packet(NETPACKET *packet) { - int sys; - int msg = msg_unpack_start(packet->data, packet->data_size, &sys); - if(sys) + if(packet->client_id == -1) { - // system message - if(msg == NETMSG_MAP) + // connectionlesss + if(packet->data_size >= (int)sizeof(SERVERBROWSE_LIST) && + memcmp(packet->data, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)) == 0) { - const char *map = msg_unpack_string(); - dbg_msg("client/network", "connection accepted, map=%s", map); - set_state(STATE_LOADING); - - if(map_load(map)) + // 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); + + info_request_begin = 0; + info_request_end = 0; + + for(int i = 0; i < servers.num; i++) { - modc_entergame(); - send_entergame(); - dbg_msg("client/network", "loading done"); - // now we will wait for two snapshots - // to finish the connection + servers.infos[i].num_players = 0; + servers.infos[i].max_players = 0; + servers.infos[i].latency = 999; + sprintf(servers.infos[i].address, "%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); } - else + } + + if(packet->data_size >= (int)sizeof(SERVERBROWSE_INFO) && + memcmp(packet->data, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0) + { + // we got ze info + data_unpacker unpacker; + unpacker.reset((unsigned char*)packet->data+sizeof(SERVERBROWSE_INFO), packet->data_size-sizeof(SERVERBROWSE_INFO)); + + for(int i = 0; i < servers.num; i++) { - error("failure to load map"); + if(net_addr4_cmp(&servers.addresses[i], &packet->address) == 0) + { + strncpy(servers.infos[i].name, unpacker.get_string(), 128); + strncpy(servers.infos[i].map, unpacker.get_string(), 128); + servers.infos[i].max_players = unpacker.get_int(); + servers.infos[i].num_players = unpacker.get_int(); + servers.infos[i].latency = ((time_get() - servers.request_times[i])*1000)/time_freq(); + dbg_msg("client", "got server info"); + break; + } } } - else if(msg == NETMSG_SNAP || msg == NETMSG_SNAPSMALL || msg == NETMSG_SNAPEMPTY) + } + else + { + + int sys; + int msg = msg_unpack_start(packet->data, packet->data_size, &sys); + if(sys) { - //dbg_msg("client/network", "got snapshot"); - int game_tick = msg_unpack_int(); - int delta_tick = game_tick-msg_unpack_int(); - int num_parts = 1; - int part = 0; - int part_size = 0; - - if(msg == NETMSG_SNAP) + // system message + if(msg == NETMSG_MAP) { - num_parts = msg_unpack_int(); - part = msg_unpack_int(); + const char *map = msg_unpack_string(); + dbg_msg("client/network", "connection accepted, map=%s", map); + set_state(STATE_LOADING); + + if(map_load(map)) + { + modc_entergame(); + send_entergame(); + dbg_msg("client/network", "loading done"); + // now we will wait for two snapshots + // to finish the connection + } + else + { + error("failure to load map"); + } } - - if(msg != NETMSG_SNAPEMPTY) - part_size = msg_unpack_int(); - - if(snapshot_part == part) + else if(msg == NETMSG_SNAP || msg == NETMSG_SNAPSMALL || msg == NETMSG_SNAPEMPTY) { - // TODO: clean this up abit - const char *d = (const char *)msg_unpack_raw(part_size); - mem_copy((char*)snapshots[SNAP_INCOMMING] + part*MAX_SNAPSHOT_PACKSIZE, d, part_size); - snapshot_part++; - - if(snapshot_part == num_parts) + //dbg_msg("client/network", "got snapshot"); + int game_tick = msg_unpack_int(); + int delta_tick = game_tick-msg_unpack_int(); + int num_parts = 1; + int part = 0; + int part_size = 0; + + if(msg == NETMSG_SNAP) { - snapshot *tmp = snapshots[SNAP_PREV]; - snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT]; - snapshots[SNAP_CURRENT] = tmp; - current_tick = game_tick; - - // decompress snapshot - void *deltadata = snapshot_empty_delta(); - int deltasize = sizeof(int)*3; - - unsigned char tmpbuffer[MAX_SNAPSHOT_SIZE]; - unsigned char tmpbuffer2[MAX_SNAPSHOT_SIZE]; - if(part_size) + num_parts = msg_unpack_int(); + part = msg_unpack_int(); + } + + if(msg != NETMSG_SNAPEMPTY) + part_size = msg_unpack_int(); + + if(snapshot_part == part) + { + // TODO: clean this up abit + const char *d = (const char *)msg_unpack_raw(part_size); + mem_copy((char*)snapshots[SNAP_INCOMMING] + part*MAX_SNAPSHOT_PACKSIZE, d, part_size); + snapshot_part++; + + if(snapshot_part == num_parts) { - int compsize = zerobit_decompress(snapshots[SNAP_INCOMMING], part_size, tmpbuffer); - int intsize = intpack_decompress(tmpbuffer, compsize, tmpbuffer2); - deltadata = tmpbuffer2; - deltasize = intsize; - } + snapshot *tmp = snapshots[SNAP_PREV]; + snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT]; + snapshots[SNAP_CURRENT] = tmp; + current_tick = game_tick; + + // decompress snapshot + void *deltadata = snapshot_empty_delta(); + int deltasize = sizeof(int)*3; + + unsigned char tmpbuffer[MAX_SNAPSHOT_SIZE]; + unsigned char tmpbuffer2[MAX_SNAPSHOT_SIZE]; + if(part_size) + { + int compsize = zerobit_decompress(snapshots[SNAP_INCOMMING], part_size, tmpbuffer); + int intsize = intpack_decompress(tmpbuffer, compsize, tmpbuffer2); + deltadata = tmpbuffer2; + deltasize = intsize; + } - // find snapshot that we should use as delta - static snapshot emptysnap; - emptysnap.data_size = 0; - emptysnap.num_items = 0; - - snapshot *deltashot = &emptysnap; - int deltashot_size; + // find snapshot that we should use as delta + static snapshot emptysnap; + emptysnap.data_size = 0; + emptysnap.num_items = 0; + + snapshot *deltashot = &emptysnap; + int deltashot_size; - if(delta_tick >= 0) - { - void *delta_data; - deltashot_size = snapshots_new.get(delta_tick, &delta_data); - if(deltashot_size >= 0) + if(delta_tick >= 0) { - deltashot = (snapshot *)delta_data; + void *delta_data; + deltashot_size = snapshots_new.get(delta_tick, &delta_data); + if(deltashot_size >= 0) + { + deltashot = (snapshot *)delta_data; + } + else + { + // TODO: handle this + dbg_msg("client", "error, couldn't find the delta snapshot"); + } } - else + + int snapsize = snapshot_unpack_delta(deltashot, (snapshot*)snapshots[SNAP_CURRENT], deltadata, deltasize); + //snapshot *shot = (snapshot *)snapshots[SNAP_CURRENT]; + + // purge old snapshots + snapshots_new.purge_until(delta_tick); + snapshots_new.purge_until(game_tick-50); // TODO: change this to server tickrate + + // add new + snapshots_new.add(game_tick, snapsize, snapshots[SNAP_CURRENT]); + + // apply snapshot, cycle pointers + recived_snapshots++; + snapshot_start_time = time_get(); + + // we got two snapshots until we see us self as connected + if(recived_snapshots == 2) { - // TODO: handle this - dbg_msg("client", "error, couldn't find the delta snapshot"); + local_start_time = time_get(); + set_state(STATE_ONLINE); } + + if(recived_snapshots > 2) + modc_newsnapshot(); + + snapshot_part = 0; + + // ack snapshot + msg_pack_start_system(NETMSG_SNAPACK, 0); + msg_pack_int(game_tick); + msg_pack_end(); + client_send_msg(); } - - int snapsize = snapshot_unpack_delta(deltashot, (snapshot*)snapshots[SNAP_CURRENT], deltadata, deltasize); - //snapshot *shot = (snapshot *)snapshots[SNAP_CURRENT]; - - // purge old snapshots - snapshots_new.purge_until(delta_tick); - snapshots_new.purge_until(game_tick-50); // TODO: change this to server tickrate - - // add new - snapshots_new.add(game_tick, snapsize, snapshots[SNAP_CURRENT]); - - // apply snapshot, cycle pointers - recived_snapshots++; - snapshot_start_time = time_get(); - - // we got two snapshots until we see us self as connected - if(recived_snapshots == 2) - { - local_start_time = time_get(); - set_state(STATE_ONLINE); - } - - if(recived_snapshots > 2) - modc_newsnapshot(); - + } + else + { + dbg_msg("client", "snapshot reset!"); snapshot_part = 0; - - // ack snapshot - msg_pack_start_system(NETMSG_SNAPACK, 0); - msg_pack_int(game_tick); - msg_pack_end(); - client_send_msg(); } } - else - { - dbg_msg("client", "snapshot reset!"); - snapshot_part = 0; - } } - } - else - { - // game message - modc_message(msg); + else + { + // game message + modc_message(msg); + } } } @@ -636,11 +777,8 @@ int main(int argc, char **argv) config_reset(); config_load("teewars.cfg"); + const char *direct_connect_server = 0x0; snd_set_master_volume(config.volume / 255.0f); - - netaddr4 server_address(127, 0, 0, 1, 8303); - //const char *name = "nameless jerk"; - bool connect_at_once = false; bool editor = false; // init network, need to be done first so we can do lookups @@ -653,24 +791,7 @@ int main(int argc, char **argv) { // -c SERVER:PORT i++; - const char *port_str = 0; - for(int k = 0; argv[i][k]; k++) - { - if(argv[i][k] == ':') - { - port_str = &(argv[i][k+1]); - argv[i][k] = 0; - break; - } - } - int port = 8303; - if(port_str) - port = atoi(port_str); - - if(net_host_lookup(argv[i], port, &server_address) != 0) - dbg_msg("main", "could not find the address of %s, connecting to localhost", argv[i]); - else - connect_at_once = true; + direct_connect_server = argv[i]; } else if(argv[i][0] == '-' && argv[i][1] == 'n' && argv[i][2] == 0 && argc - i > 1) { @@ -695,7 +816,7 @@ int main(int argc, char **argv) { // start the client client c; - c.run(connect_at_once ? &server_address : 0x0); + c.run(direct_connect_server); } return 0; } diff --git a/src/engine/interface.h b/src/engine/interface.h index d23067fb..4cadb996 100644 --- a/src/engine/interface.h +++ b/src/engine/interface.h @@ -689,7 +689,7 @@ void modmenu_shutdown(); Function: modmenu_render Called every frame to let the menu render it self. */ -int modmenu_render(void *server_address); +int modmenu_render(); @@ -752,9 +752,19 @@ float gfx_pretty_text_width(float size, const char *text); void mods_message(int msg, int client_id); void modc_message(int msg); -#define MASTER_SERVER_ADDRESS "master.teewars.com" -#define MASTER_SERVER_PORT 8300 +struct server_info +{ + int max_players; + int num_players; + int latency; // in ms + char name[128]; + char map[128]; + char address[128]; +}; +void client_connect(const char *address); +void client_serverbrowse_refresh(); +int client_serverbrowse_getlist(server_info **servers); #endif diff --git a/src/engine/network.cpp b/src/engine/network.cpp index 3abe44b0..c6b8207f 100644 --- a/src/engine/network.cpp +++ b/src/engine/network.cpp @@ -18,20 +18,6 @@ unsigned char crc[2]; 6 */ - -// move -static int net_addr4_cmp(const NETADDR4 *a, const NETADDR4 *b) -{ - if( a->ip[0] != b->ip[0] || - a->ip[1] != b->ip[1] || - a->ip[2] != b->ip[2] || - a->ip[3] != b->ip[3] || - a->port != b->port - ) - return 1; - return 0; -} - enum { NETWORK_VERSION = 1, @@ -51,7 +37,7 @@ enum NETWORK_PACKETFLAG_CLOSE=0x04, NETWORK_PACKETFLAG_VITAL=0x08, NETWORK_PACKETFLAG_RESEND=0x10, - //NETWORK_PACKETFLAG_STATELESS=0x20, + NETWORK_PACKETFLAG_CONNLESS=0x20, }; struct NETPACKETDATA @@ -208,7 +194,7 @@ static void conn_send(NETCONNECTION *conn, int flags, int data_size, const void p.data_size = data_size; p.data = (unsigned char *)data; p.first_send_time = time_get(); - + if(flags&NETWORK_PACKETFLAG_VITAL) { // save packet if we need to resend @@ -321,7 +307,7 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETDATA *p, NETADDR4 *addr) static void conn_update(NETCONNECTION *conn) { - if(conn->state == NETWORK_CONNSTATE_ERROR) + if(conn->state == NETWORK_CONNSTATE_OFFLINE || conn->state == NETWORK_CONNSTATE_ERROR) return; // check for timeout @@ -479,58 +465,71 @@ int net_server_recv(NETSERVER *s, NETPACKET *packet) int r = check_packet(s->recv_buffer, bytes, &data); if(r == 0) { - // ok packet, process it - if(data.flags == NETWORK_PACKETFLAG_CONNECT) + if(data.flags&NETWORK_PACKETFLAG_CONNLESS) { - int found = 0; - - // check if we already got this client - for(int i = 0; i < NETWORK_MAX_CLIENTS; i++) - { - if(s->slots[i].conn.state != NETWORK_CONNSTATE_OFFLINE && - net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0) - { - found = 1; // silent ignore.. we got this client already - break; - } - } - - // client that wants to connect - if(!found) + // connection less packets + packet->client_id = -1; + packet->address = addr; + packet->flags = PACKETFLAG_CONNLESS; + packet->data_size = data.data_size; + packet->data = data.data; + return 1; + } + else + { + // ok packet, process it + if(data.flags == NETWORK_PACKETFLAG_CONNECT) { + int found = 0; + + // check if we already got this client for(int i = 0; i < NETWORK_MAX_CLIENTS; i++) { - if(s->slots[i].conn.state == NETWORK_CONNSTATE_OFFLINE) + if(s->slots[i].conn.state != NETWORK_CONNSTATE_OFFLINE && + net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0) { - conn_feed(&s->slots[i].conn, &data, &addr); - found = 1; + found = 1; // silent ignore.. we got this client already break; } } + + // client that wants to connect + if(!found) + { + for(int i = 0; i < NETWORK_MAX_CLIENTS; i++) + { + if(s->slots[i].conn.state == NETWORK_CONNSTATE_OFFLINE) + { + conn_feed(&s->slots[i].conn, &data, &addr); + found = 1; + break; + } + } + } + + if(!found) + { + // TODO: send error + } } - - if(!found) - { - // TODO: send error - } - } - else - { - // find matching slot - for(int i = 0; i < NETWORK_MAX_CLIENTS; i++) + else { - if(net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0) + // find matching slot + for(int i = 0; i < NETWORK_MAX_CLIENTS; i++) { - if(conn_feed(&s->slots[i].conn, &data, &addr)) + if(net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0) { - if(data.data_size) + if(conn_feed(&s->slots[i].conn, &data, &addr)) { - packet->client_id = i; - packet->address = addr; - packet->flags = 0; - packet->data_size = data.data_size; - packet->data = data.data; - return 1; + if(data.data_size) + { + packet->client_id = i; + packet->address = addr; + packet->flags = 0; + packet->data_size = data.data_size; + packet->data = data.data; + return 1; + } } } } @@ -540,6 +539,7 @@ int net_server_recv(NETSERVER *s, NETPACKET *packet) else { // errornous packet, drop it + dbg_msg("server", "crazy packet"); } // read header @@ -551,10 +551,27 @@ int net_server_recv(NETSERVER *s, NETPACKET *packet) int net_server_send(NETSERVER *s, NETPACKET *packet) { - // TODO: insert stuff for stateless stuff - dbg_assert(packet->client_id >= 0, "errornous client id"); - dbg_assert(packet->client_id < NETWORK_MAX_CLIENTS, "errornous client id"); - conn_send(&s->slots[packet->client_id].conn, 0, packet->data_size, packet->data); + if(packet->flags&PACKETFLAG_CONNLESS) + { + // send connectionless packet + NETPACKETDATA p; + p.ID[0] = 'T'; + p.ID[1] = 'W'; + p.version = NETWORK_VERSION; + p.flags = NETWORK_PACKETFLAG_CONNLESS; + p.seq = 0; + p.ack = 0; + p.crc = 0; + p.data_size = packet->data_size; + p.data = (unsigned char *)packet->data; + send_packet(s->socket, &packet->address, &p); + } + else + { + dbg_assert(packet->client_id >= 0, "errornous client id"); + dbg_assert(packet->client_id < NETWORK_MAX_CLIENTS, "errornous client id"); + conn_send(&s->slots[packet->client_id].conn, 0, packet->data_size, packet->data); + } return 0; } @@ -574,11 +591,11 @@ void net_server_stats(NETSERVER *s, NETSTATS *stats) } // -NETCLIENT *net_client_open(int flags) +NETCLIENT *net_client_open(int port, int flags) { NETCLIENT *client = (NETCLIENT *)mem_alloc(sizeof(NETCLIENT), 1); mem_zero(client, sizeof(NETCLIENT)); - client->socket = net_udp4_create(0); + client->socket = net_udp4_create(port); conn_init(&client->conn, client->socket); return client; } @@ -626,23 +643,37 @@ int net_client_recv(NETCLIENT *c, NETPACKET *packet) NETPACKETDATA data; int r = check_packet(c->recv_buffer, bytes, &data); - if(r == 0 && conn_feed(&c->conn, &data, &addr)) - { - // fill in packet - packet->client_id = 0; - packet->address = addr; - packet->flags = 0; - packet->data_size = data.data_size; - packet->data = data.data; - return 1; - } - else + + if(r == 0) { - // errornous packet, drop it + if(data.flags&NETWORK_PACKETFLAG_CONNLESS) + { + // connection less packets + packet->client_id = -1; + packet->address = addr; + packet->flags = PACKETFLAG_CONNLESS; + packet->data_size = data.data_size; + packet->data = data.data; + return 1; + } + else + { + if(conn_feed(&c->conn, &data, &addr)) + { + // fill in packet + packet->client_id = 0; + packet->address = addr; + packet->flags = 0; + packet->data_size = data.data_size; + packet->data = data.data; + return 1; + } + else + { + // errornous packet, drop it + } + } } - - // read header - // do checksum } return 0; @@ -650,9 +681,27 @@ int net_client_recv(NETCLIENT *c, NETPACKET *packet) int net_client_send(NETCLIENT *c, NETPACKET *packet) { - // TODO: insert stuff for stateless stuff - dbg_assert(packet->client_id == 0, "errornous client id"); - conn_send(&c->conn, 0, packet->data_size, packet->data); + if(packet->flags&PACKETFLAG_CONNLESS) + { + // send connectionless packet + NETPACKETDATA p; + p.ID[0] = 'T'; + p.ID[1] = 'W'; + p.version = NETWORK_VERSION; + p.flags = NETWORK_PACKETFLAG_CONNLESS; + p.seq = 0; + p.ack = 0; + p.crc = 0; + p.data_size = packet->data_size; + p.data = (unsigned char *)packet->data; + send_packet(c->socket, &packet->address, &p); + } + else + { + // TODO: insert stuff for stateless stuff + dbg_assert(packet->client_id == 0, "errornous client id"); + conn_send(&c->conn, 0, packet->data_size, packet->data); + } return 0; } diff --git a/src/engine/network.h b/src/engine/network.h index de035888..e251f13e 100644 --- a/src/engine/network.h +++ b/src/engine/network.h @@ -28,6 +28,7 @@ enum { NETFLAG_ALLOWSTATELESS=1, PACKETFLAG_VITAL=1, + PACKETFLAG_CONNLESS=2, NETSTATE_OFFLINE=0, NETSTATE_CONNECTING, @@ -46,7 +47,7 @@ int net_server_delclient(NETSERVER *s); // -1 when no more, else, client id void net_server_stats(NETSERVER *s, NETSTATS *stats); // client side -NETCLIENT *net_client_open(int flags); +NETCLIENT *net_client_open(int port, int flags); int net_client_disconnect(NETCLIENT *c, const char *reason); int net_client_connect(NETCLIENT *c, NETADDR4 *addr); int net_client_recv(NETCLIENT *c, NETPACKET *packet); @@ -88,7 +89,7 @@ public: net_client() : ptr(0) {} ~net_client() { close(); } - int open(int flags) { ptr = net_client_open(flags); return ptr != 0; } + int open(int port, int flags) { ptr = net_client_open(port, flags); return ptr != 0; } int close() { int r = net_client_close(ptr); ptr = 0; return r; } int connect(NETADDR4 *addr) { return net_client_connect(ptr, addr); } diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 6fe84ade..87380cfa 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -15,6 +15,7 @@ #include <engine/network.h> #include <engine/config.h> +#include <mastersrv/mastersrv.h> namespace baselib {} using namespace baselib; @@ -162,11 +163,14 @@ public: //for(int i = 0; i < MAX_CLIENTS; i++) //dbg_msg("network/server", "\t%d: %d", i, clients[i].state); - if (net_host_lookup(MASTER_SERVER_ADDRESS, MASTER_SERVER_PORT, &master_server) != 0) + if (net_host_lookup(MASTERSERVER_ADDRESS, MASTERSERVER_PORT, &master_server) != 0) { // TODO: fix me //master_server = netaddr4(0, 0, 0, 0, 0); } + + dbg_msg("server", "masterserver = %d.%d.%d.%d:%d", + master_server.ip[0], master_server.ip[1], master_server.ip[2], master_server.ip[3], master_server.port); mods_init(); @@ -178,13 +182,15 @@ public: lastheartbeat = 0; int64 reporttime = time_get(); - int64 reportinterval = time_freq()*3; + int reportinterval = 3; + //int64 reportinterval = time_freq()*3; int64 simulationtime = 0; int64 snaptime = 0; int64 networktime = 0; + int64 totaltime = 0; - while(1) + while(true) { int64 t = time_get(); if(t-lasttick > time_per_tick) @@ -204,23 +210,11 @@ public: lasttick += time_per_tick; } - if(send_heartbeats) + //if(send_heartbeats) { if (t > lastheartbeat+time_per_heartbeat) { - if (master_server.port != 0) - { - int players = 0; - - for (int i = 0; i < MAX_CLIENTS; i++) - if (!clients[i].is_empty()) - players++; - - // TODO: fix me - netaddr4 me(127, 0, 0, 0, 8303); - //send_heartbeat(0, &me, players, MAX_CLIENTS, server_name, mapname); - } - + send_heartbeat(); lastheartbeat = t+time_per_heartbeat; } } @@ -233,37 +227,21 @@ public: if(reporttime < time_get()) { - int64 totaltime = simulationtime+snaptime+networktime; dbg_msg("server/report", "sim=%.02fms snap=%.02fms net=%.02fms total=%.02fms load=%.02f%%", - simulationtime/(float)reportinterval*1000, - snaptime/(float)reportinterval*1000, - networktime/(float)reportinterval*1000, - totaltime/(float)reportinterval*1000, - (simulationtime+snaptime+networktime)/(float)reportinterval*100.0f); - - unsigned sent_total=0, recv_total=0; - /* - for (int i = 0; i < MAX_CLIENTS; i++) - if (!clients[i].is_empty()) - { - unsigned s,r; - clients[i].conn.counter_get(&s,&r); - clients[i].conn.counter_reset(); - sent_total += s; - recv_total += r; - } - */ - - dbg_msg("server/report", "biggestsnap=%d send=%d recv=%d", - biggest_snapshot, sent_total/3, recv_total/3); + (simulationtime/reportinterval)/(double)time_freq()*1000, + (snaptime/reportinterval)/(double)time_freq()*1000, + (networktime/reportinterval)/(double)time_freq()*1000, + (totaltime/reportinterval)/(double)time_freq()*1000, + (totaltime)/reportinterval/(double)time_freq()*100.0f); simulationtime = 0; snaptime = 0; networktime = 0; + totaltime = 0; - reporttime += reportinterval; + reporttime += time_freq()*reportinterval; } - + totaltime += time_get()-t; thread_sleep(1); } @@ -382,6 +360,18 @@ public: msg_pack_end(); server_send_msg(cid); } + + void send_heartbeat() + { + dbg_msg("server", "sending heartbeat"); + NETPACKET packet; + packet.client_id = -1; + packet.address = master_server; + packet.flags = PACKETFLAG_CONNLESS; + packet.data_size = sizeof(SERVERBROWSE_HEARTBEAT); + packet.data = SERVERBROWSE_HEARTBEAT; + net.send(&packet); + } void drop(int cid, const char *reason) { @@ -450,6 +440,27 @@ public: drop(clientId, "client timedout"); } + void send_serverinfo(NETADDR4 *addr) + { + dbg_msg("server", "sending heartbeat"); + NETPACKET packet; + + data_packer packer; + packer.reset(); + packer.add_raw(SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)); + packer.add_string(server_name, 128); + packer.add_string(map_name, 128); + packer.add_int(8); // max_players + packer.add_int(0); // num_players + + packet.client_id = -1; + packet.address = *addr; + packet.flags = PACKETFLAG_CONNLESS; + packet.data_size = packer.size(); + packet.data = packer.data(); + net.send(&packet); + } + void pump_network() { net.update(); @@ -458,10 +469,16 @@ public: NETPACKET packet; while(net.recv(&packet)) { - if(packet.client_id == -1) { // stateless + if(packet.data_size == sizeof(SERVERBROWSE_GETINFO) && + memcmp(packet.data, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0) + { + dbg_msg("server", "info requested"); + send_serverinfo(&packet.address); + + } } else process_client_packet(&packet); |