diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-12-15 10:24:49 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-12-15 10:24:49 +0000 |
| commit | a2566b3ebd93e0bbc55a920a7be08054a9377f11 (patch) | |
| tree | 44a4612805d894168fe4b3b4c065fccc1a1686e9 /src/engine/network.c | |
| parent | ac9873056aa1fe529b098f19ff31e9ffa0e016a2 (diff) | |
| download | zcatch-a2566b3ebd93e0bbc55a920a7be08054a9377f11.tar.gz zcatch-a2566b3ebd93e0bbc55a920a7be08054a9377f11.zip | |
cleaned up code structure a bit
Diffstat (limited to 'src/engine/network.c')
| -rw-r--r-- | src/engine/network.c | 937 |
1 files changed, 0 insertions, 937 deletions
diff --git a/src/engine/network.c b/src/engine/network.c deleted file mode 100644 index 85b4604f..00000000 --- a/src/engine/network.c +++ /dev/null @@ -1,937 +0,0 @@ -/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ -#include <string.h> -#include <stdio.h> - -#include "system.h" -#include "config.h" -#include "network.h" - -/* - header (6 bytes) - unsigned char flags; 1 - unsigned char seq_ack[3]; 4 - unsigned char token[2]; 6 -*/ - -enum -{ - NETWORK_VERSION = 1, - - NETWORK_HEADER_SIZE = 6, - NETWORK_MAX_PAYLOAD = 1024, - NETWORK_MAX_PACKET_SIZE = NETWORK_HEADER_SIZE+NETWORK_MAX_PAYLOAD, - NETWORK_MAX_CLIENTS = 16, - - NETWORK_CONNSTATE_OFFLINE=0, - NETWORK_CONNSTATE_CONNECT=1, - NETWORK_CONNSTATE_CONNECTACCEPTED=2, - NETWORK_CONNSTATE_ONLINE=3, - NETWORK_CONNSTATE_ERROR=4, - - NETWORK_PACKETFLAG_CONNECT=0x01, - NETWORK_PACKETFLAG_ACCEPT=0x02, - NETWORK_PACKETFLAG_CLOSE=0x04, - NETWORK_PACKETFLAG_VITAL=0x08, - NETWORK_PACKETFLAG_RESEND=0x10, - NETWORK_PACKETFLAG_CONNLESS=0x20, - - NETWORK_MAX_SEQACK=0x1000 -}; - -static int current_token = 1; - -typedef struct -{ - unsigned char ID[2]; - unsigned char version; - unsigned char flags; - unsigned short seq; - unsigned short ack; - unsigned crc; - int token; - unsigned data_size; - int64 first_send_time; - unsigned char *data; -} NETPACKETDATA; - - -static void send_packet(NETSOCKET socket, NETADDR4 *addr, NETPACKETDATA *packet) -{ - unsigned char buffer[NETWORK_MAX_PACKET_SIZE]; - int send_size = NETWORK_HEADER_SIZE+packet->data_size; - - buffer[0] = packet->flags; - buffer[1] = ((packet->seq>>4)&0xf0) | ((packet->ack>>8)&0x0f); - buffer[2] = packet->seq; - buffer[3] = packet->ack; - buffer[4] = packet->token>>8; - buffer[5] = packet->token&0xff; - mem_copy(buffer+NETWORK_HEADER_SIZE, packet->data, packet->data_size); - net_udp4_send(socket, addr, buffer, send_size); -} - -typedef struct RINGBUFFER_ITEM_t -{ - struct RINGBUFFER_ITEM_t *next; - struct RINGBUFFER_ITEM_t *prev; - int size; -} RINGBUFFER_ITEM; - -typedef struct -{ - RINGBUFFER_ITEM *first; - RINGBUFFER_ITEM *last; - unsigned buffer_size; -} RINGBUFFER; - -static void rb_init(RINGBUFFER *rb) -{ - rb->first = 0; - rb->last = 0; - rb->buffer_size = 0; -} - -static void *rb_item_data(RINGBUFFER_ITEM *item) -{ - return (void*)(item+1); -} - -static void *rb_alloc(RINGBUFFER *rb, int size) -{ - RINGBUFFER_ITEM *item = (RINGBUFFER_ITEM*)mem_alloc(sizeof(RINGBUFFER_ITEM)+size, 1); - item->size = size; - - item->prev = rb->last; - item->next = 0; - if(rb->last) - rb->last->next = item; - else - rb->first = item; - rb->last = item; - - rb->buffer_size += size; - return rb_item_data(item); -} - -static void rb_pop_first(RINGBUFFER *rb) -{ - if(rb->first) - { - RINGBUFFER_ITEM *next = rb->first->next; - rb->buffer_size -= rb->first->size; - mem_free(rb->first); - rb->first = next; - if(rb->first) - rb->first->prev = NULL; - else - rb->last = NULL; - } -} - -static void rb_clear(RINGBUFFER *rb) -{ - while(rb->first) - rb_pop_first(rb); -} - - -typedef struct -{ - unsigned short seq; - unsigned short ack; - unsigned state; - - int token; - - int remote_closed; - - int connected; - int disconnected; - - RINGBUFFER buffer; - - int64 last_update_time; - int64 last_recv_time; - int64 last_send_time; - - char error_string[256]; - - NETADDR4 peeraddr; - NETSOCKET socket; - NETSTATS stats; -} NETCONNECTION; - -typedef struct -{ - NETCONNECTION conn; -} NETSLOT; - -struct NETSERVER_t -{ - NETSOCKET socket; - NETSLOT slots[NETWORK_MAX_CLIENTS]; - int max_clients; - NETFUNC_NEWCLIENT new_client; - NETFUNC_NEWCLIENT del_client; - void *user_ptr; - unsigned char recv_buffer[NETWORK_MAX_PACKET_SIZE]; -} ; - -struct NETCLIENT_t -{ - NETADDR4 server_addr; - NETSOCKET socket; - unsigned char recv_buffer[NETWORK_MAX_PACKET_SIZE]; - - NETCONNECTION conn; -}; - -static void conn_reset_stats(NETCONNECTION *conn) -{ - mem_zero(&conn->stats, sizeof(conn->stats)); -} - -static void conn_reset(NETCONNECTION *conn) -{ - conn->seq = 0; - conn->ack = 0; - conn->remote_closed = 0; - - if(conn->state == NETWORK_CONNSTATE_ONLINE || - conn->state == NETWORK_CONNSTATE_ERROR) - { - conn->disconnected++; - } - - conn->state = NETWORK_CONNSTATE_OFFLINE; - conn->last_send_time = 0; - conn->last_recv_time = 0; - conn->last_update_time = 0; - conn->token = -1; - - rb_clear(&conn->buffer); -} - - -static const char *conn_error(NETCONNECTION *conn) -{ - return conn->error_string; -} - -static void conn_set_error(NETCONNECTION *conn, const char *str) -{ - strcpy(conn->error_string, str); -} - -/* -static int conn_state(NETCONNECTION *conn) -{ - return conn->state; -}*/ - -static void conn_init(NETCONNECTION *conn, NETSOCKET socket) -{ - conn_reset(conn); - conn_reset_stats(conn); - conn->socket = socket; - conn->connected = 0; - conn->disconnected = 0; - rb_init(&conn->buffer); - mem_zero(conn->error_string, sizeof(conn->error_string)); -} - -static void conn_ack(NETCONNECTION *conn, int ack) -{ - while(1) - { - RINGBUFFER_ITEM *item = conn->buffer.first; - NETPACKETDATA *resend; - if(!item) - break; - - resend = (NETPACKETDATA *)rb_item_data(item); - if(resend->seq <= ack || (ack < NETWORK_MAX_SEQACK/3 && resend->seq > NETWORK_MAX_SEQACK/2)) - rb_pop_first(&conn->buffer); - else - break; - } -} - -static void conn_send_raw(NETCONNECTION *conn, NETPACKETDATA *data) -{ - conn->last_send_time = time_get(); - conn->stats.send_packets++; - conn->stats.send_bytes += data->data_size + NETWORK_HEADER_SIZE; - send_packet(conn->socket, &conn->peeraddr, data); -} - -static void conn_resend(NETCONNECTION *conn) -{ - RINGBUFFER_ITEM *item = conn->buffer.first; - while(item) - { - NETPACKETDATA *resend = (NETPACKETDATA *)rb_item_data(item); - conn->stats.resend_packets++; - conn->stats.resend_bytes += resend->data_size + NETWORK_HEADER_SIZE; - conn_send_raw(conn, resend); - item = item->next; - } -} - -static void conn_send(NETCONNECTION *conn, int flags, int data_size, const void *data) -{ - NETPACKETDATA p; - - if(flags&NETWORK_PACKETFLAG_VITAL) - conn->seq = (conn->seq+1)%NETWORK_MAX_SEQACK; - - p.ID[0] = 'T'; - p.ID[1] = 'W'; - p.version = NETWORK_VERSION; - p.flags = flags; - p.seq = conn->seq; - p.ack = conn->ack; - p.crc = 0; - p.token = conn->token; - 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 */ - NETPACKETDATA *resend = (NETPACKETDATA *)rb_alloc(&conn->buffer, sizeof(NETPACKETDATA)+data_size); - *resend = p; - resend->data = (unsigned char *)(resend+1); - mem_copy(resend->data, p.data, p.data_size); - } - - /* TODO: calc crc */ - conn_send_raw(conn, &p); -} - -static int conn_connect(NETCONNECTION *conn, NETADDR4 *addr) -{ - if(conn->state != NETWORK_CONNSTATE_OFFLINE) - return -1; - - /* init connection */ - conn_reset(conn); - conn->peeraddr = *addr; - conn->token = current_token++; - mem_zero(conn->error_string, sizeof(conn->error_string)); - conn->state = NETWORK_CONNSTATE_CONNECT; - conn_send(conn, NETWORK_PACKETFLAG_CONNECT, 0, 0); - return 0; -} - -static void conn_disconnect(NETCONNECTION *conn, const char *reason) -{ - if(conn->remote_closed == 0) - { - if(reason) - conn_send(conn, NETWORK_PACKETFLAG_CLOSE, strlen(reason)+1, reason); - else - conn_send(conn, NETWORK_PACKETFLAG_CLOSE, 0, 0); - - conn->error_string[0] = 0; - if(reason) - strcpy(conn->error_string, reason); - } - - conn_reset(conn); -} - -static int conn_feed(NETCONNECTION *conn, NETPACKETDATA *p, NETADDR4 *addr) -{ - conn->last_recv_time = time_get(); - conn->stats.recv_packets++; - conn->stats.recv_bytes += p->data_size + NETWORK_HEADER_SIZE; - - if(p->flags&NETWORK_PACKETFLAG_CLOSE) - { - conn->state = NETWORK_CONNSTATE_ERROR; - conn->remote_closed = 1; - - if(p->data_size) - conn_set_error(conn, (char *)p->data); - else - conn_set_error(conn, "no reason given"); - if(config.debug) - dbg_msg("conn", "closed reason='%s'", conn_error(conn)); - return 0; - } - - if(conn->state == NETWORK_CONNSTATE_OFFLINE) - { - if(p->flags == NETWORK_PACKETFLAG_CONNECT) - { - /* send response and init connection */ - conn->state = NETWORK_CONNSTATE_ONLINE; - conn->connected++; - conn->peeraddr = *addr; - conn->token = p->token; - conn_send(conn, NETWORK_PACKETFLAG_CONNECT|NETWORK_PACKETFLAG_ACCEPT, 0, 0); - if(config.debug) - dbg_msg("connection", "got connection, sending connect+accept"); - } - } - else if(net_addr4_cmp(&conn->peeraddr, addr) == 0) - { - if(p->token != conn->token) - return 0; - - if(conn->state == NETWORK_CONNSTATE_ONLINE) - { - /* remove packages that are acked */ - conn_ack(conn, p->ack); - - /* check if resend is requested */ - if(p->flags&NETWORK_PACKETFLAG_RESEND) - conn_resend(conn); - - if(p->flags&NETWORK_PACKETFLAG_VITAL) - { - if(p->seq == (conn->ack+1)%NETWORK_MAX_SEQACK) - { - /* in sequence */ - conn->ack = (conn->ack+1)%NETWORK_MAX_SEQACK; - } - else - { - /* out of sequence, request resend */ - dbg_msg("conn", "asking for resend %d %d", p->seq, (conn->ack+1)%NETWORK_MAX_SEQACK); - conn_send(conn, NETWORK_PACKETFLAG_RESEND, 0, 0); - return 0; - } - } - else - { - if(p->seq > conn->ack) - conn_send(conn, NETWORK_PACKETFLAG_RESEND, 0, 0); - } - - if(p->data_size == 0) - return 0; - - return 1; - } - else if(conn->state == NETWORK_CONNSTATE_CONNECT) - { - /* connection made */ - if(p->flags == (NETWORK_PACKETFLAG_CONNECT|NETWORK_PACKETFLAG_ACCEPT)) - { - conn_send(conn, NETWORK_PACKETFLAG_ACCEPT, 0, 0); - conn->state = NETWORK_CONNSTATE_ONLINE; - conn->connected++; - dbg_msg("connection", "got connect+accept, sending accept. connection online"); - } - } - /* - else if(conn->state == NETWORK_CONNSTATE_CONNECTACCEPTED) - { - // connection made - if(p->flags == NETWORK_PACKETFLAG_ACCEPT) - { - conn->state = NETWORK_CONNSTATE_ONLINE; - dbg_msg("connection", "got accept. connection online"); - } - }*/ - else - { - /* strange packet, wrong state */ - conn->state = NETWORK_CONNSTATE_ERROR; - conn_set_error(conn, "strange state and packet"); - } - } - else - { - /* strange packet, not ment for me */ - } - - return 0; -} - - - -static int conn_update(NETCONNECTION *conn) -{ - int64 now = time_get(); - - if(conn->state == NETWORK_CONNSTATE_OFFLINE || conn->state == NETWORK_CONNSTATE_ERROR) - return 0; - - /* watch out for major hitches */ - { - int64 delta = now-conn->last_update_time; - if(conn->last_update_time && delta > time_freq()/2) - { - RINGBUFFER_ITEM *item = conn->buffer.first; - - dbg_msg("conn", "hitch %d", (int)((delta*1000)/time_freq())); - conn->last_recv_time += delta; - - while(item) - { - NETPACKETDATA *resend = (NETPACKETDATA *)rb_item_data(item); - resend->first_send_time += delta; - item = item->next; - } - } - - conn->last_update_time = now; - } - - - /* check for timeout */ - if(conn->state != NETWORK_CONNSTATE_OFFLINE && - conn->state != NETWORK_CONNSTATE_CONNECT && - (now-conn->last_recv_time) > time_freq()*10) - { - conn->state = NETWORK_CONNSTATE_ERROR; - conn_set_error(conn, "timeout"); - } - - /* check for large buffer errors */ - if(conn->buffer.buffer_size > 1024*64) - { - conn->state = NETWORK_CONNSTATE_ERROR; - conn_set_error(conn, "too weak connection (out of buffer)"); - } - - if(conn->buffer.first) - { - NETPACKETDATA *resend = (NETPACKETDATA *)(conn->buffer.first+1); - if(now-resend->first_send_time > time_freq()*10) - { - conn->state = NETWORK_CONNSTATE_ERROR; - conn_set_error(conn, "too weak connection (not acked for 10 seconds)"); - } - } - - /* send keep alives if nothing has happend for 250ms */ - if(conn->state == NETWORK_CONNSTATE_ONLINE) - { - if(time_get()-conn->last_send_time> time_freq()/4) - conn_send(conn, NETWORK_PACKETFLAG_VITAL, 0, 0); - } - else if(conn->state == NETWORK_CONNSTATE_CONNECT) - { - if(time_get()-conn->last_send_time > time_freq()/2) /* send a new connect every 500ms */ - conn_send(conn, NETWORK_PACKETFLAG_CONNECT, 0, 0); - } - else if(conn->state == NETWORK_CONNSTATE_CONNECTACCEPTED) - { - if(time_get()-conn->last_send_time > time_freq()/2) /* send a new connect/accept every 500ms */ - conn_send(conn, NETWORK_PACKETFLAG_CONNECT|NETWORK_PACKETFLAG_ACCEPT, 0, 0); - } - - return 0; -} - - -static int check_packet(unsigned char *buffer, int size, NETPACKETDATA *packet) -{ - /* check the size */ - if(size < NETWORK_HEADER_SIZE || size > NETWORK_MAX_PACKET_SIZE) - return -1; - - /* read the packet */ - packet->ID[0] = 'T'; - packet->ID[1] = 'W'; - packet->version = NETWORK_VERSION; - packet->flags = buffer[0]; - packet->seq = ((buffer[1]&0xf0)<<4)|buffer[2]; - packet->ack = ((buffer[1]&0x0f)<<8)|buffer[3]; - packet->crc = 0; - packet->token = (buffer[4]<<8)|buffer[5]; - packet->data_size = size - NETWORK_HEADER_SIZE; - packet->data = buffer+NETWORK_HEADER_SIZE; - - /* check the packet */ - if(packet->ID[0] != 'T' || packet->ID[1] != 'W') - return 1; - - if(packet->version != NETWORK_VERSION) - return 1; - - /* TODO: perform crc check */ - - /* return success */ - return 0; -} - -NETSERVER *netserver_open(NETADDR4 bindaddr, int max_clients, int flags) -{ - int i; - NETSERVER *server; - NETSOCKET socket = net_udp4_create(bindaddr); - if(socket == NETSOCKET_INVALID) - return 0; - - server = (NETSERVER *)mem_alloc(sizeof(NETSERVER), 1); - mem_zero(server, sizeof(NETSERVER)); - server->socket = socket; - server->max_clients = max_clients; - if(server->max_clients > NETWORK_MAX_CLIENTS) - server->max_clients = NETWORK_MAX_CLIENTS; - if(server->max_clients < 1) - server->max_clients = 1; - - for(i = 0; i < NETWORK_MAX_CLIENTS; i++) - conn_init(&server->slots[i].conn, server->socket); - - return server; -} - -int netserver_set_callbacks(NETSERVER *s, NETFUNC_NEWCLIENT new_client, NETFUNC_DELCLIENT del_client, void *user) -{ - s->new_client = new_client; - s->del_client = del_client; - s->user_ptr = user; - return 0; -} - -int netserver_max_clients(NETSERVER *s) -{ - return s->max_clients; -} - -int netserver_close(NETSERVER *s) -{ - /* TODO: implement me */ - return 0; -} - -int netserver_drop(NETSERVER *s, int client_id, const char *reason) -{ - /* TODO: insert lots of checks here */ - dbg_msg("net_server", "client dropped. cid=%d reason=\"%s\"", client_id, reason); - conn_disconnect(&s->slots[client_id].conn, reason); - - if(s->del_client) - s->del_client(client_id, s->user_ptr); - - return 0; -} - -int netserver_update(NETSERVER *s) -{ - int i; - for(i = 0; i < s->max_clients; i++) - { - conn_update(&s->slots[i].conn); - if(s->slots[i].conn.state == NETWORK_CONNSTATE_ERROR) - netserver_drop(s, i, conn_error(&s->slots[i].conn)); - } - return 0; -} - -int netserver_recv(NETSERVER *s, NETPACKET *packet) -{ - NETPACKETDATA data; - int i, r, bytes, found; - NETADDR4 addr; - - while(1) - { - bytes = net_udp4_recv(s->socket, &addr, s->recv_buffer, NETWORK_MAX_PACKET_SIZE); - - /* no more packets for now */ - if(bytes <= 0) - break; - - r = check_packet(s->recv_buffer, bytes, &data); - if(r == 0) - { - 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 - { - /* ok packet, process it */ - if(data.flags == NETWORK_PACKETFLAG_CONNECT) - { - found = 0; - - /* check if we already got this client */ - for(i = 0; i < s->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) - { - for(i = 0; i < s->max_clients; i++) - { - if(s->slots[i].conn.state == NETWORK_CONNSTATE_OFFLINE) - { - found = 1; - conn_feed(&s->slots[i].conn, &data, &addr); - if(s->new_client) - s->new_client(i, s->user_ptr); - break; - } - } - } - - if(!found) - { - /* send connectionless packet */ - const char errstring[] = "server full"; - NETPACKETDATA p; - p.ID[0] = 'T'; - p.ID[1] = 'W'; - p.version = NETWORK_VERSION; - p.flags = NETWORK_PACKETFLAG_CLOSE; - p.seq = 0; - p.ack = 0; - p.crc = 0; - p.token = data.token; - p.data_size = sizeof(errstring); - p.data = (unsigned char *)errstring; - send_packet(s->socket, &addr, &p); - } - } - else - { - /* find matching slot */ - for(i = 0; i < s->max_clients; i++) - { - if(net_addr4_cmp(&s->slots[i].conn.peeraddr, &addr) == 0) - { - if(conn_feed(&s->slots[i].conn, &data, &addr)) - { - 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; - } - } - } - } - } - } - } - else - { - /* errornous packet, drop it */ - dbg_msg("server", "crazy packet"); - } - - /* read header */ - /* do checksum */ - } - - return 0; -} - -int netserver_send(NETSERVER *s, NETPACKET *packet) -{ - dbg_assert(packet->data_size < NETWORK_MAX_PAYLOAD, "packet payload too big"); - - 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 - { - int flags = 0; - dbg_assert(packet->client_id >= 0, "errornous client id"); - dbg_assert(packet->client_id < s->max_clients, "errornous client id"); - if(packet->flags&PACKETFLAG_VITAL) - flags |= NETWORK_PACKETFLAG_VITAL; - conn_send(&s->slots[packet->client_id].conn, flags, packet->data_size, packet->data); - } - return 0; -} - -void netserver_stats(NETSERVER *s, NETSTATS *stats) -{ - int num_stats = sizeof(NETSTATS)/sizeof(int); - int *istats = (int *)stats; - int c, i; - - mem_zero(stats, sizeof(NETSTATS)); - - for(c = 0; c < s->max_clients; c++) - { - if(s->slots[c].conn.state != NETWORK_CONNSTATE_OFFLINE) - { - int *sstats = (int *)(&(s->slots[c].conn.stats)); - for(i = 0; i < num_stats; i++) - istats[i] += sstats[i]; - } - } -} - -NETCLIENT *netclient_open(NETADDR4 bindaddr, int flags) -{ - NETCLIENT *client = (NETCLIENT *)mem_alloc(sizeof(NETCLIENT), 1); - mem_zero(client, sizeof(NETCLIENT)); - client->socket = net_udp4_create(bindaddr); - conn_init(&client->conn, client->socket); - return client; -} - -int netclient_close(NETCLIENT *c) -{ - /* TODO: implement me */ - return 0; -} - -int netclient_update(NETCLIENT *c) -{ - conn_update(&c->conn); - if(c->conn.state == NETWORK_CONNSTATE_ERROR) - netclient_disconnect(c, conn_error(&c->conn)); - return 0; -} - -int netclient_disconnect(NETCLIENT *c, const char *reason) -{ - dbg_msg("netclient", "disconnected. reason=\"%s\"", reason); - conn_disconnect(&c->conn, reason); - return 0; -} - -int netclient_connect(NETCLIENT *c, NETADDR4 *addr) -{ - conn_connect(&c->conn, addr); - return 0; -} - -int netclient_recv(NETCLIENT *c, NETPACKET *packet) -{ - while(1) - { - NETADDR4 addr; - NETPACKETDATA data; - int r; - int bytes = net_udp4_recv(c->socket, &addr, c->recv_buffer, NETWORK_MAX_PACKET_SIZE); - - /* no more packets for now */ - if(bytes <= 0) - break; - - r = check_packet(c->recv_buffer, bytes, &data); - - if(r == 0) - { - 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 */ - } - } - } - } - - return 0; -} - -int netclient_send(NETCLIENT *c, NETPACKET *packet) -{ - dbg_assert(packet->data_size < NETWORK_MAX_PAYLOAD, "packet payload too big"); - - 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.token = 0; - p.data_size = packet->data_size; - p.data = (unsigned char *)packet->data; - send_packet(c->socket, &packet->address, &p); - } - else - { - int flags = 0; - dbg_assert(packet->client_id == 0, "errornous client id"); - if(packet->flags&PACKETFLAG_VITAL) - flags |= NETWORK_PACKETFLAG_VITAL; - conn_send(&c->conn, flags, packet->data_size, packet->data); - } - return 0; -} - -int netclient_state(NETCLIENT *c) -{ - if(c->conn.state == NETWORK_CONNSTATE_ONLINE) - return NETSTATE_ONLINE; - if(c->conn.state == NETWORK_CONNSTATE_OFFLINE) - return NETSTATE_OFFLINE; - return NETSTATE_CONNECTING; -} - -int netclient_gotproblems(NETCLIENT *c) -{ - if(time_get() - c->conn.last_recv_time > time_freq()) - return 1; - return 0; -} - -void netclient_stats(NETCLIENT *c, NETSTATS *stats) -{ - *stats = c->conn.stats; -} - -const char *netclient_error_string(NETCLIENT *c) -{ - return conn_error(&c->conn); -} |