diff options
Diffstat (limited to 'src/engine/e_network_server.c')
| -rw-r--r-- | src/engine/e_network_server.c | 484 |
1 files changed, 0 insertions, 484 deletions
diff --git a/src/engine/e_network_server.c b/src/engine/e_network_server.c deleted file mode 100644 index 8ec65504..00000000 --- a/src/engine/e_network_server.c +++ /dev/null @@ -1,484 +0,0 @@ -#include <base/system.h> -#include "e_network.h" -#include "e_network_internal.h" - -typedef struct -{ - NETCONNECTION conn; -} NETSLOT; - -typedef struct NETBAN -{ - NETBANINFO info; - - /* hash list */ - struct NETBAN *hashnext; - struct NETBAN *hashprev; - - /* used or free list */ - struct NETBAN *next; - struct NETBAN *prev; -} NETBAN; - -#define MACRO_LIST_LINK_FIRST(object, first, prev, next) \ - { if(first) first->prev = object; \ - object->prev = (void*)0; \ - object->next = first; \ - first = object; } - -#define MACRO_LIST_LINK_AFTER(object, after, prev, next) \ - { object->prev = after; \ - object->next = after->next; \ - after->next = object; \ - if(object->next) \ - object->next->prev = object; \ - } - -#define MACRO_LIST_UNLINK(object, first, prev, next) \ - { if(object->next) object->next->prev = object->prev; \ - if(object->prev) object->prev->next = object->next; \ - else first = object->next; \ - object->next = 0; object->prev = 0; } - -#define MACRO_LIST_FIND(start, next, expression) \ - { while(start && !(expression)) start = start->next; } - -struct NETSERVER -{ - NETSOCKET socket; - NETSLOT slots[NET_MAX_CLIENTS]; - int max_clients; - - NETBAN *bans[256]; - NETBAN banpool[NET_SERVER_MAXBANS]; - NETBAN *banpool_firstfree; - NETBAN *banpool_firstused; - - NETFUNC_NEWCLIENT new_client; - NETFUNC_NEWCLIENT del_client; - void *user_ptr; - - NETRECVINFO recv; -}; - -NETSERVER *netserver_open(NETADDR bindaddr, int max_clients, int flags) -{ - int i; - NETSERVER *server; - NETSOCKET socket = net_udp_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 > NET_MAX_CLIENTS) - server->max_clients = NET_MAX_CLIENTS; - if(server->max_clients < 1) - server->max_clients = 1; - - for(i = 0; i < NET_MAX_CLIENTS; i++) - conn_init(&server->slots[i].conn, server->socket); - - /* setup all pointers for bans */ - for(i = 1; i < NET_SERVER_MAXBANS-1; i++) - { - server->banpool[i].next = &server->banpool[i+1]; - server->banpool[i].prev = &server->banpool[i-1]; - } - - server->banpool[0].next = &server->banpool[1]; - server->banpool[NET_SERVER_MAXBANS-1].prev = &server->banpool[NET_SERVER_MAXBANS-2]; - server->banpool_firstfree = &server->banpool[0]; - - 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 */ - NETADDR addr; - netserver_client_addr(s, client_id, &addr); - - dbg_msg("net_server", "client dropped. cid=%d ip=%d.%d.%d.%d reason=\"%s\"", - client_id, - addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3], - 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_ban_get(NETSERVER *s, int index, NETBANINFO *info) -{ - NETBAN *ban; - for(ban = s->banpool_firstused; ban && index; ban = ban->next, index--) - {} - - if(!ban) - return 0; - *info = ban->info; - return 1; -} - -int netserver_ban_num(NETSERVER *s) -{ - int count = 0; - NETBAN *ban; - for(ban = s->banpool_firstused; ban; ban = ban->next) - count++; - return count; -} - -static void netserver_ban_remove_by_object(NETSERVER *s, NETBAN *ban) -{ - int iphash = (ban->info.addr.ip[0]+ban->info.addr.ip[1]+ban->info.addr.ip[2]+ban->info.addr.ip[3])&0xff; - dbg_msg("netserver", "removing ban on %d.%d.%d.%d", - ban->info.addr.ip[0], ban->info.addr.ip[1], ban->info.addr.ip[2], ban->info.addr.ip[3]); - MACRO_LIST_UNLINK(ban, s->banpool_firstused, prev, next); - MACRO_LIST_UNLINK(ban, s->bans[iphash], hashprev, hashnext); - MACRO_LIST_LINK_FIRST(ban, s->banpool_firstfree, prev, next); -} - -int netserver_ban_remove(NETSERVER *s, NETADDR addr) -{ - int iphash = (addr.ip[0]+addr.ip[1]+addr.ip[2]+addr.ip[3])&0xff; - NETBAN *ban = s->bans[iphash]; - - MACRO_LIST_FIND(ban, hashnext, net_addr_comp(&ban->info.addr, &addr) == 0); - - if(ban) - { - netserver_ban_remove_by_object(s, ban); - return 0; - } - - return -1; -} - -int netserver_ban_add(NETSERVER *s, NETADDR addr, int seconds) -{ - int iphash = (addr.ip[0]+addr.ip[1]+addr.ip[2]+addr.ip[3])&0xff; - unsigned stamp = 0xffffffff; - NETBAN *ban; - - /* remove the port */ - addr.port = 0; - - if(seconds) - stamp = time_timestamp() + seconds; - - /* search to see if it already exists */ - ban = s->bans[iphash]; - MACRO_LIST_FIND(ban, hashnext, net_addr_comp(&ban->info.addr, &addr) == 0); - if(ban) - { - /* adjust the ban */ - ban->info.expires = stamp; - return 0; - } - - if(!s->banpool_firstfree) - return -1; - - /* fetch and clear the new ban */ - ban = s->banpool_firstfree; - MACRO_LIST_UNLINK(ban, s->banpool_firstfree, prev, next); - - /* setup the ban info */ - ban->info.expires = stamp; - ban->info.addr = addr; - - /* add it to the ban hash */ - MACRO_LIST_LINK_FIRST(ban, s->bans[iphash], hashprev, hashnext); - - /* insert it into the used list */ - { - if(s->banpool_firstused) - { - NETBAN *insert_after = s->banpool_firstused; - MACRO_LIST_FIND(insert_after, next, stamp < insert_after->info.expires); - - if(insert_after) - insert_after = insert_after->prev; - else - { - /* add to last */ - insert_after = s->banpool_firstused; - while(insert_after->next) - insert_after = insert_after->next; - } - - if(insert_after) - { - MACRO_LIST_LINK_AFTER(ban, insert_after, prev, next); - } - else - { - MACRO_LIST_LINK_FIRST(ban, s->banpool_firstused, prev, next); - } - } - else - { - MACRO_LIST_LINK_FIRST(ban, s->banpool_firstused, prev, next); - } - } - - /* drop banned clients */ - { - char buf[128]; - int i; - NETADDR banaddr; - - if(seconds) - str_format(buf, sizeof(buf), "you have been banned for %d minutes", seconds/60); - else - str_format(buf, sizeof(buf), "you have been banned for life"); - - for(i = 0; i < s->max_clients; i++) - { - banaddr = s->slots[i].conn.peeraddr; - banaddr.port = 0; - - if(net_addr_comp(&addr, &banaddr) == 0) - netserver_drop(s, i, buf); - } - } - return 0; -} - -int netserver_update(NETSERVER *s) -{ - unsigned now = time_timestamp(); - - int i; - for(i = 0; i < s->max_clients; i++) - { - conn_update(&s->slots[i].conn); - if(s->slots[i].conn.state == NET_CONNSTATE_ERROR) - netserver_drop(s, i, conn_error(&s->slots[i].conn)); - } - - /* remove expired bans */ - while(s->banpool_firstused && s->banpool_firstused->info.expires < now) - { - NETBAN *ban = s->banpool_firstused; - netserver_ban_remove_by_object(s, ban); - } - - (void)now; - - return 0; -} - -/* - TODO: chopp up this function into smaller working parts -*/ -int netserver_recv(NETSERVER *s, NETCHUNK *chunk) -{ - unsigned now = time_timestamp(); - - while(1) - { - NETADDR addr; - int i, bytes, found; - - /* check for a chunk */ - if(recvinfo_fetch_chunk(&s->recv, chunk)) - return 1; - - /* TODO: empty the recvinfo */ - bytes = net_udp_recv(s->socket, &addr, s->recv.buffer, NET_MAX_PACKETSIZE); - - /* no more packets for now */ - if(bytes <= 0) - break; - - if(unpack_packet(s->recv.buffer, bytes, &s->recv.data) == 0) - { - NETBAN *ban = 0; - NETADDR banaddr = addr; - int iphash = (addr.ip[0]+addr.ip[1]+addr.ip[2]+addr.ip[3])&0xff; - found = 0; - banaddr.port = 0; - - /* search a ban */ - for(ban = s->bans[iphash]; ban; ban = ban->hashnext) - { - if(net_addr_comp(&ban->info.addr, &banaddr) == 0) - break; - } - - /* check if we just should drop the packet */ - if(ban) - { - // banned, reply with a message - char banstr[128]; - if(ban->info.expires) - { - int mins = ((ban->info.expires - now)+59)/60; - if(mins == 1) - str_format(banstr, sizeof(banstr), "banned for %d minute", mins); - else - str_format(banstr, sizeof(banstr), "banned for %d minutes", mins); - } - else - str_format(banstr, sizeof(banstr), "banned for life"); - send_controlmsg(s->socket, &addr, 0, NET_CTRLMSG_CLOSE, banstr, str_length(banstr)+1); - continue; - } - - if(s->recv.data.flags&NET_PACKETFLAG_CONNLESS) - { - chunk->flags = NETSENDFLAG_CONNLESS; - chunk->client_id = -1; - chunk->address = addr; - chunk->data_size = s->recv.data.data_size; - chunk->data = s->recv.data.chunk_data; - return 1; - } - else - { - /* TODO: check size here */ - if(s->recv.data.flags&NET_PACKETFLAG_CONTROL && s->recv.data.chunk_data[0] == NET_CTRLMSG_CONNECT) - { - found = 0; - - /* check if we already got this client */ - for(i = 0; i < s->max_clients; i++) - { - if(s->slots[i].conn.state != NET_CONNSTATE_OFFLINE && - net_addr_comp(&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 == NET_CONNSTATE_OFFLINE) - { - found = 1; - conn_feed(&s->slots[i].conn, &s->recv.data, &addr); - if(s->new_client) - s->new_client(i, s->user_ptr); - break; - } - } - - if(!found) - { - const char fullmsg[] = "server is full"; - send_controlmsg(s->socket, &addr, 0, NET_CTRLMSG_CLOSE, fullmsg, sizeof(fullmsg)); - } - } - } - else - { - /* normal packet, find matching slot */ - for(i = 0; i < s->max_clients; i++) - { - if(net_addr_comp(&s->slots[i].conn.peeraddr, &addr) == 0) - { - if(conn_feed(&s->slots[i].conn, &s->recv.data, &addr)) - { - if(s->recv.data.data_size) - recvinfo_start(&s->recv, &addr, &s->slots[i].conn, i); - } - } - } - } - } - } - } - return 0; -} - -int netserver_send(NETSERVER *s, NETCHUNK *chunk) -{ - if(chunk->data_size >= NET_MAX_PAYLOAD) - { - dbg_msg("netserver", "packet payload too big. %d. dropping packet", chunk->data_size); - return -1; - } - - if(chunk->flags&NETSENDFLAG_CONNLESS) - { - /* send connectionless packet */ - send_packet_connless(s->socket, &chunk->address, chunk->data, chunk->data_size); - } - else - { - int f = 0; - dbg_assert(chunk->client_id >= 0, "errornous client id"); - dbg_assert(chunk->client_id < s->max_clients, "errornous client id"); - - if(chunk->flags&NETSENDFLAG_VITAL) - f = NET_CHUNKFLAG_VITAL; - - conn_queue_chunk(&s->slots[chunk->client_id].conn, f, chunk->data_size, chunk->data); - - if(chunk->flags&NETSENDFLAG_FLUSH) - conn_flush(&s->slots[chunk->client_id].conn); - } - 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 != NET_CONNSTATE_OFFLINE) - { - int *sstats = (int *)(&(s->slots[c].conn.stats)); - for(i = 0; i < num_stats; i++) - istats[i] += sstats[i]; - } - } -} - -NETSOCKET netserver_socket(NETSERVER *s) -{ - return s->socket; -} - - -int netserver_client_addr(NETSERVER *s, int client_id, NETADDR *addr) -{ - *addr = s->slots[client_id].conn.peeraddr; - return 1; -} |