diff --git a/ChangeLog b/ChangeLog index 6fe49c5..ed082bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,23 @@ -$Id: ChangeLog,v 1.107 2006/07/30 11:44:57 stpohle Exp $ +$Id: ChangeLog,v 1.108 2006/08/13 21:26:50 stpohle Exp $ Version 0.11.7 (still in progress) +- Testing: Security Problems found by Luigi Auriemma + Bugs: A] memcpy crash in rscache_add + B] information disclosure in send_pkg + C] simple error message termination + for more informations look here: + http://aluigi.altervista.org/adv/bcloneboom-adv.txt + Solutions to + A) rewrote the whole resend cache system, also send_mapinfo needed a + bad workaround for a bug i couldn't find out. + B) made sure that the size of a packet is set right before send over + the network. Found only the function (do_gameinfo) where something + like this occured. + do_pkg will also check the size of the incoming packet with the + p->h.len value. + C) accept the error packets only from the server of a game. Since only the + server will send such type of packets. + - Fixed: Security Problem found by Stefan Cornelius. For more information look here: https://lists.uni-koeln.de/pipermail/sec-info/Week-of-Mon-20060313/006561.html diff --git a/bomberclone.prj b/bomberclone.prj index 86dcd7c..ddc09d0 100644 --- a/bomberclone.prj +++ b/bomberclone.prj @@ -68,8 +68,7 @@ project.configure.options= anjuta.program.arguments= preferences.build.option.jobs=0 preferences.build.option.silent=0 -preferences.build.option.autosave=0 -preferences.anjuta.make.options=-k +preferences.build.option.autosave=1 preferences.make=make preferences.build.option.keep.going=0 preferences.build.option.warn.undef=0 diff --git a/include/basic.h b/include/basic.h index 988dad1..f815026 100644 --- a/include/basic.h +++ b/include/basic.h @@ -1,4 +1,4 @@ -/* $Id: basic.h,v 1.34 2006/07/30 11:44:57 stpohle Exp $ */ +/* $Id: basic.h,v 1.35 2006/08/13 21:26:50 stpohle Exp $ */ /* basic types which we need everywhere */ #ifndef _BC_BASIC_H_ @@ -192,7 +192,7 @@ enum _help_page { struct { Sint16 x; Sint16 y; -} typedef _point; +} __attribute__((packed)) typedef _point; struct { diff --git a/include/network.h b/include/network.h index 2823f67..f17dacc 100644 --- a/include/network.h +++ b/include/network.h @@ -1,4 +1,4 @@ -/* $Id: network.h,v 1.23 2004/12/26 04:19:21 stpohle Exp $ +/* $Id: network.h,v 1.24 2006/08/13 21:26:50 stpohle Exp $ * network.h file... for everything what have to do with the network stuff */ @@ -9,7 +9,7 @@ #define _NETWORK_H_ #define MAX_UDPDATA 1024 -#define PKG_RESENDCACHE_SIZE (64*1024) +#define PKG_RESENDCACHE_SIZE 64 #define PKG_IN_INDEX_NUM 512 #define RESENDCACHE_TIMEOUT 400 #define RESENDCACHE_TIMEOUT_MENU 3000 @@ -61,7 +61,7 @@ struct { // this holds the network data char host[LEN_SERVERNAME]; char port[LEN_PORT]; struct _sockaddr sAddr; - signed char pl_nr; // pl_nr so we know it in the pkgcahce. + signed char pl_nr; // pl_nr so we know it in the pkgcache. } typedef _net_addr; diff --git a/include/packets.h b/include/packets.h index dfebd7e..4adf2c2 100644 --- a/include/packets.h +++ b/include/packets.h @@ -1,4 +1,4 @@ -/* $Id: packets.h,v 1.32 2005/03/27 01:31:50 stpohle Exp $ +/* $Id: packets.h,v 1.33 2006/08/13 21:26:50 stpohle Exp $ * network packets.. */ #ifndef _PACKETS_H_ @@ -55,47 +55,40 @@ struct pkgheader { unsigned char flags; Sint16 id; Sint16 len; -}; - +} __attribute__((packed)); struct pkg { struct pkgheader h; char data[0]; -}; - +} __attribute__((packed)); struct pkg_bcmservchat { char typ; char data[128]; -}; - +} __attribute__((packed)); struct pkg_tunneldata { struct pkgheader h; signed char tunnel_nr; _point target; -}; - +} __attribute__((packed)); struct pkg_pkgack { struct pkgheader h; char typ; Sint16 id; -}; - +} __attribute__((packed)); struct pkg_ping { struct pkgheader h; Sint32 data; -}; - +} __attribute__((packed)); struct pkg_contest { struct pkgheader h; signed char from; signed char to; -}; - +} __attribute__((packed)); struct pkg_teamdata { struct pkgheader h; @@ -103,14 +96,13 @@ struct pkg_teamdata { signed char col; signed char wins; char name[LEN_PLAYERNAME]; -}; - +} __attribute__((packed)); struct pkgdropitemelemt { signed char x; signed char y; unsigned char typ; -}; +} __attribute__((packed)); struct pkg_dropitem { struct pkgheader h; @@ -118,8 +110,7 @@ struct pkg_dropitem { signed char pl_nr; // playernumber -1 if the server jsut dropped something unsigned char count; // number of elements struct pkgdropitemelemt items[0]; // elements -}; - +} __attribute__((packed)); struct pkg_field { struct pkgheader h; @@ -134,17 +125,15 @@ struct pkg_field { unsigned char frame; unsigned char bomb_b; unsigned char bomb_p; - } ex[4]; // count up every explosion there is on this field for ever direction + } ex[4]; // count up every explosion there is on this field for ever direction Sint32 ex_nr; // number to identify the explosion. -}; - +} __attribute__((packed)); struct pkg_error { struct pkgheader h; unsigned char nr; char text[128]; -}; - +} __attribute__((packed)); struct pkg_servermode { struct pkgheader h; @@ -164,8 +153,7 @@ struct pkg_servermode { signed char p_nr; /* if the server sends this to a client... it will be the clients in_nr number (-1) for not set */ -}; - +} __attribute__((packed)); struct pkg_joingame { struct pkgheader h; @@ -175,8 +163,7 @@ struct pkg_joingame { signed char secondplayer; // this is the second player char name[LEN_PLAYERNAME]; char password[LEN_PASSWORD]; -}; - +} __attribute__((packed)); struct pkg_playerid { struct pkgheader h; @@ -192,8 +179,7 @@ struct pkg_playerid { signed char team_nr; // team number Sint16 team_points; // team points Sint16 team_wins; // team wins -}; - +} __attribute__((packed)); struct pkg_playerdata { struct pkgheader h; @@ -210,8 +196,7 @@ struct pkg_playerdata { unsigned char frame; signed char dead_by; signed char ready; // if the player is ready for the game -}; - +} __attribute__((packed)); struct pkg_playermove { struct pkgheader h; @@ -221,8 +206,7 @@ struct pkg_playermove { Sint16 speed; Sint16 tunnelto; _point pos; -}; - +} __attribute__((packed)); struct pkg_bombdata { struct pkgheader h; @@ -237,50 +221,45 @@ struct pkg_bombdata { Uint16 destx; Uint16 desty; Sint16 speed; -}; - +} __attribute__((packed)); struct pkg_quit { struct pkgheader h; signed char pl_nr; signed char new_server; -}; - +} __attribute__((packed)); struct pkg_getfield { struct pkgheader h; signed char line; -}; - +} __attribute__((packed)); struct pkg_playerstatus { struct pkgheader h; signed char pl_nr; signed char net_istep; signed char status; -}; - +} __attribute__((packed)); struct pkg_fieldline { struct pkgheader h; signed char line; unsigned char type[MAX_FIELDSIZE_X]; unsigned char special[MAX_FIELDSIZE_X]; -}; - +} __attribute__((packed)); struct pkg_ill { struct pkgheader h; signed char pl_nr; Sint32 to[PI_max]; -}; +} __attribute__((packed)); struct pkg_updateinfo { struct pkgheader h; signed char pl_nr; unsigned char step[MAX_PLAYERS]; unsigned char status[MAX_PLAYERS]; -}; +} __attribute__((packed)); struct pkg_respawn { struct pkgheader h; @@ -288,28 +267,24 @@ struct pkg_respawn { signed char x; signed char y; unsigned char state; -}; - +} __attribute__((packed)); struct pkg_getplayerdata { struct pkgheader h; signed char pl_nr; -}; - +} __attribute__((packed)); struct pkg_chat { struct pkgheader h; char text[128]; -}; - +} __attribute__((packed)); struct pkg_special { struct pkgheader h; signed char pl_nr; Sint32 ex_nr; unsigned char typ; -}; - +} __attribute__((packed)); struct pkg_mapinfo { struct pkgheader h; @@ -330,8 +305,7 @@ struct pkg_mapinfo { unsigned char start_range; char start_speed[8]; // to make sure there will be no difference char bomb_tickingtime[8]; // to make sure there will be no difference -}; - +} __attribute__((packed)); /* this packet type is also used in netsrvlist.c */ struct pkg_gameinfo { @@ -343,34 +317,29 @@ struct pkg_gameinfo { char version[LEN_VERSION]; char broadcast; signed char password; /* if password == -1, we do a game request */ -}; - +} __attribute__((packed)); +/* structures needed by the resend cache */ struct _rscache_entry { - signed char pl_nr; // playernumber to whom this data should go - Sint16 len; // size of the entry Uint32 timestamp; // pointer to the timestamp signed char retry; // retry's how many times we tryed this - _net_addr addr; // pointer to the address - struct pkg packet; // pointer to the packet -}; - + _net_addr addr; // the address + struct pkg packet; // the packet + char data[MAX_UDPDATA]; // packet data without header +} __attribute__((packed)); struct _resend_cache { - char *data; // will hold the pointer to out cache - struct _rscache_entry *entry; // pointer to our data - Sint32 fill; // how much we have used + struct _rscache_entry entry[PKG_RESENDCACHE_SIZE]; // pointer to our data + int count; }; - struct _inpkg_index { signed char pl_nr; unsigned char typ; Sint16 id; }; - -extern int do_error (struct pkg_error *data, _net_addr *addr); +extern void do_error (struct pkg_error *data, _net_addr *addr); extern void do_playerid (struct pkg_playerid *p_id, _net_addr *addr); extern void do_servermode (struct pkg_servermode *s_mod, _net_addr *addr); extern void do_joingame (struct pkg_joingame *p_jg, _net_addr * addr); @@ -387,7 +356,7 @@ extern void do_getplayerdata (struct pkg_getplayerdata *gp_dat, _net_addr *addr) extern void do_playerstatus (struct pkg_playerstatus *gp_dat, _net_addr *addr); extern void do_pkgack (struct pkg_pkgack *p_ack, _net_addr *addr); extern void do_chat (struct pkg_chat *chat_pkg, _net_addr *addr); -extern int do_pkg (struct pkg *packet, _net_addr *addr); +extern void do_pkg (struct pkg *packet, _net_addr *addr, int len); extern void do_bcmservchat (struct pkg_bcmservchat *packet, _net_addr *addr); extern void do_ill (struct pkg_ill *ill_pkg, _net_addr *addr); extern void do_special (struct pkg_special *sp_pkg, _net_addr *addr); @@ -434,12 +403,11 @@ extern int inpkg_check (unsigned char typ, short int id, _net_addr *addr); extern void inpkg_delplayer (int pl_nr); /* this functions will be defined in pkgcache.c */ -extern int rscache_add (_net_addr *addr, struct pkg *packet); -extern void rscache_del (); -extern int rscache_getpos (_net_addr *addr, unsigned char typ, short int id); -extern int rscache_getcurlen (); +extern void rscache_init (); +extern void rscache_add (_net_addr *addr, struct pkg *packet); +extern void rscache_del (_net_addr *addr, unsigned char typ, short unsigned int id); extern void rscache_loop (); -extern struct _resend_cache resend_cache; +extern struct _resend_cache rscache; #endif diff --git a/src/configuration.c b/src/configuration.c index 130fe6d..13d7e2f 100644 --- a/src/configuration.c +++ b/src/configuration.c @@ -1,4 +1,4 @@ -/* $Id: configuration.c,v 1.78 2006/08/13 21:20:54 patty21 Exp $ +/* $Id: configuration.c,v 1.79 2006/08/13 21:26:50 stpohle Exp $ * configuration */ #include @@ -93,8 +93,7 @@ config_init (int argc, char **argv) sprintf (bman.port, "%d", DEFAULT_UDPPORT); sprintf (bman.ogcserver, DEFAULT_GAMECACHE); sprintf (bman.ogc_port, DEFAULT_GAMECACHEPORT); - resend_cache.data = NULL; - resend_cache.fill = -1; + rscache.count = 0; bman.notifygamemaster = 1; bman.broadcast = 1; bman.autostart = AUTOSTART; diff --git a/src/debug.c b/src/debug.c index 95e29de..418b001 100644 --- a/src/debug.c +++ b/src/debug.c @@ -40,7 +40,7 @@ void d_playerdetail (char *head) { d_printf ("---------------> %s\n", head); d_printf ("Nr Name GFX Sta Pkt Win Team net_flag [Addr]\n"); for (i = 0; i < MAX_PLAYERS; i++) - d_printf ("%2d %16s %3d %3d %3d %3d %4d %3d [%s:%s]\n",i, players[i].name, players[i].gfx_nr, players[i].state, players[i].points, players[i].wins, players[i].team_nr, players[i].net.flags, players[i].net.addr.host, players[i].net.addr.port); + d_printf ("%2d %16s %3d %3d %3d %3d %4d %3d %p[%s:%s]\n",i, players[i].name, players[i].gfx_nr, players[i].state, players[i].points, players[i].wins, players[i].team_nr, players[i].net.flags, players[i].net.addr.host, &players[i].net.addr, players[i].net.addr.port); }; diff --git a/src/network.c b/src/network.c index 98480f5..71c7ba8 100644 --- a/src/network.c +++ b/src/network.c @@ -1,4 +1,4 @@ -/* $Id: network.c,v 1.76 2005/08/07 17:46:21 stpohle Exp $ */ +/* $Id: network.c,v 1.77 2006/08/13 21:26:50 stpohle Exp $ */ /* network routines. */ @@ -133,9 +133,8 @@ network_init () } // we have got our socket.. so now allocate the memory for the resend_cache - resend_cache.data = (char *) malloc (PKG_RESENDCACHE_SIZE); - resend_cache.fill = 0; - + rscache_init (); + return 0; }; @@ -180,12 +179,6 @@ network_shutdown () udp_close (bman.sock); - if (resend_cache.data != NULL) - free (resend_cache.data); - - resend_cache.data = NULL; - resend_cache.fill = -1; - bman.p_nr = -1; bman.sock = -1; #ifdef _WIN32 @@ -250,7 +243,7 @@ network_loop () &addr.sAddr); while (inlen > 0) { - do_pkg (packet, &addr); + do_pkg (packet, &addr, inlen); // printf ("Network : inlen (%d) typ (%d) Size (%d)\n", inlen, packet->typ, pkglen); inlen = udp_get (bman.sock, data, MAX_UDPDATA, &addr.sAddr, bman.net_ai_family); diff --git a/src/packets.c b/src/packets.c index b57e29c..f6a3759 100644 --- a/src/packets.c +++ b/src/packets.c @@ -61,19 +61,19 @@ send_error (_net_addr * addr, char *text) }; -int +void do_error (struct pkg_error *data, _net_addr * addr) { d_printf ("Network Error from %s:%s : '%s'\n", addr->host, addr->port, data->text); - network_shutdown (); - - menu_displaymessage ("Network Error", "Got Error from: %s:%s\nMessage:%s", addr->host, - addr->port, data->text); - if (data->nr == 1) - return -1; - else - return 0; + /* check if the packet comes from the server, the server + * never gets errormessages from a client, if a client has + * some trouble the client will just disconnect */ + if (GT_MP_PTPS && addr->pl_nr == bman.p_servnr) { + menu_displaymessage ("Network Error", "Got Error from: %s:%s\nMessage:%s", addr->host, + addr->port, data->text); + network_shutdown (); + } }; @@ -98,7 +98,7 @@ do_joingame (struct pkg_joingame *p_jg, _net_addr * addr) vsu; char text[255]; - d_printf ("do_joingame (From:%s:%s Player(name:%s)\n", addr->host, addr->port, p_jg->name); + d_printf ("do_joingame (From:%s:%s Player(name:%s) addr:%p\n", addr->host, addr->port, p_jg->name, addr); sscanf (VERSION, "%d.%d.%d", &vma, &vmi, &vsu); @@ -185,9 +185,12 @@ do_joingame (struct pkg_joingame *p_jg, _net_addr * addr) bman.players_nr_s++; /* send to the new client the servermode and the complete playerlist */ + printf ("ADDR: %p\n", addr); if ((!p_jg->secondplayer) && !(players[j].net.flags & NETF_local2)) send_mapinfo (addr); + printf ("ADDR: %p\n", addr); send_servermode (addr, i); // with this packet the client know it'S pl_nr + printf ("ADDR: %p\n", addr); addr->pl_nr = i; } @@ -611,30 +614,32 @@ void send_servermode (_net_addr * addr, int pl_nr) { struct pkg_servermode s_mod; - + switch (bman.state) { case (GS_startup): - d_printf ("Send ServerMode : startup\n"); + d_printf ("Send ServerMode : startup"); break; case (GS_ready): - d_printf ("Send ServerMode : ready\n"); + d_printf ("Send ServerMode : ready"); break; case (GS_running): - d_printf ("Send ServerMode : running\n"); + d_printf ("Send ServerMode : running"); break; case (GS_quit): - d_printf ("Send ServerMode : quit\n"); + d_printf ("Send ServerMode : quit"); break; case (GS_wait): - d_printf ("Send ServerMode : wait\n"); + d_printf ("Send ServerMode : wait"); break; case (GS_update): - d_printf ("Send ServerMode : update\n"); + d_printf ("Send ServerMode : update"); break; default: - d_printf ("Send ServerMode : mode %d\n", s_mod.state); + d_printf ("Send ServerMode : mode %d", s_mod.state); } + d_printf ("Addr: %p\n", addr); + s_mod.h.typ = PKG_servermode; s_mod.h.len = HTON16 (sizeof (struct pkg_servermode)); s_mod.h.flags = PKGF_ackreq; @@ -1467,10 +1472,7 @@ void do_pkgack (struct pkg_pkgack *p_ack, _net_addr * addr) { d_printf ("do_pkgack (%s:%s)\n", addr->host, addr->port); - if (rscache_getpos (addr, p_ack->typ, NTOH16 (p_ack->id)) == -1) - return; - - rscache_del (); + rscache_del (addr, p_ack->typ, NTOH16 (p_ack->id)); }; @@ -1573,7 +1575,9 @@ void send_mapinfo (_net_addr * addr) { struct pkg_mapinfo map_pkg; - +#ifndef BUG_MAPINFO + _net_addr *test; // VERY DIRTY WORKAROUND WHY IS HERE A BUG +#endif map_pkg.h.typ = PKG_mapinfo; map_pkg.h.len = HTON16 (sizeof (struct pkg_mapinfo)); map_pkg.h.flags = PKGF_ackreq; @@ -1589,17 +1593,25 @@ send_mapinfo (_net_addr * addr) map_pkg.sp_push = map.sp_push; map_pkg.start_bombs = bman.start_bombs; map_pkg.start_range = bman.start_range; - sprintf (map_pkg.start_speed, "%6f", bman.start_speed); - sprintf (map_pkg.bomb_tickingtime, "%6f", bman.bomb_tickingtime); + sprintf (map_pkg.start_speed, "%4f", bman.start_speed); + sprintf (map_pkg.bomb_tickingtime, "%4f", bman.bomb_tickingtime); if (map.random_tileset) map_pkg.tileset[0] = 0; else - strcpy (map_pkg.tileset, map.tileset); + strncpy (map_pkg.tileset, map.tileset, LEN_TILESETNAME); map_pkg.map_selection = map.map_selection; - strcpy (map_pkg.mapname, map.map); + strncpy (map_pkg.mapname, map.map, LEN_FILENAME); d_printf ("send_mapinfo: Tileset: %s\n", map.tileset); +#ifndef BUG_MAPINFO + test = addr; // VERY DIRTY WORKAROUND WHY IS HERE A BUG send_pkg ((struct pkg *) &map_pkg, addr); + addr = test; // VERY DIRTY WORKAROUND WHY IS HERE A BUG +#else + printf ("Addr before send: %p\n", addr); + send_pkg ((struct pkg *) &map_pkg, addr); + printf ("Addr after send: %p\n", addr); +#endif }; @@ -1618,9 +1630,9 @@ do_mapinfo (struct pkg_mapinfo *map_pkg, _net_addr * addr) } else { map.random_tileset = 0; - strcpy (map.tileset, map_pkg->tileset); + strncpy (map.tileset, map_pkg->tileset, LEN_TILESETNAME); } - strcpy (map.map, map_pkg->mapname); + strncpy (map.map, map_pkg->mapname, LEN_FILENAME); map.map_selection = map_pkg->map_selection; map.size.x = map_pkg->size_x; map.size.y = map_pkg->size_y; @@ -1703,6 +1715,7 @@ do_gameinfo (struct pkg_gameinfo *pgi, _net_addr * addr) strncpy (pgi->version, VERSION, LEN_VERSION); pgi->maxplayers = bman.maxplayer; pgi->curplayers = bman.players_nr_s; + pgi->h.len = HTON16 (sizeof (struct pkg_gameinfo)); strncpy (pgi->gamename, bman.gamename, LEN_GAMENAME); send_pkg ((struct pkg *) pgi, addr); } @@ -1711,7 +1724,6 @@ do_gameinfo (struct pkg_gameinfo *pgi, _net_addr * addr) else d_printf ("do_gameinfo (from: %s:%s) ** WE ARE NOT THE MASTER OF THIS GAME **\n", addr->host, addr->port); - } @@ -1807,10 +1819,8 @@ send_pkg (struct pkg *packet, _net_addr * addr) /* if PKGF_ackreq is set add the packet to the resendcache * so we can resend it if no PKF_ackreq returned for the packet. */ - if (packet->h.flags & PKGF_ackreq) { - if (rscache_add (addr, packet) == -1) - d_printf ("resend_cache overrun.... packet throw away.\n"); - } + if (packet->h.flags & PKGF_ackreq) + rscache_add (addr, packet); }; @@ -1841,15 +1851,22 @@ fwd_pkg (struct pkg *packet, _net_addr * addr) forward it to all needed functions, like inpkg_check()--> send answer if needed, if we are the server then forward the packet if needed and go into the do_PACKETTYP function */ -int -do_pkg (struct pkg *packet, _net_addr * addr) +void +do_pkg (struct pkg *packet, _net_addr * addr, int len) { + d_printf ("do_pkg: addr %p, pkg %p\n", addr, packet); if (((packet->h.flags & PKGF_ipv6) == 0 && bman.net_ai_family != PF_INET) || ((packet->h.flags & PKGF_ipv6) != 0 && bman.net_ai_family == PF_INET)) { d_printf ("do_pkg: packet comes from the wrong network type\n"); - return 0; + return; } + /* Check the size of the incoming packet */ + if (len != NTOH16(packet->h.len)) { + d_printf ("do_pkg: len of the incoming packet is not the same as in pkg->h.len\n"); + return; + } + /* get the addr and set the ping timeout value * check if the packet is from a player in the game and not from someone else * this exception is only for PKG_joingame, PKG_error */ @@ -1857,7 +1874,7 @@ do_pkg (struct pkg *packet, _net_addr * addr) if ((addr->pl_nr < 0 || addr->pl_nr >= MAX_PLAYERS) && packet->h.typ > PKG_joingame && PS_IS_netplayer (players[addr->pl_nr].state)) { d_printf ("do_pkg: error addr->pl_nr out of range\n"); - return 0; + return; } if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) { @@ -1881,7 +1898,7 @@ do_pkg (struct pkg *packet, _net_addr * addr) d_printf ("do_pkg: double packet ignoring addr->pl_nr=%d\n", addr->pl_nr); if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) players[addr->pl_nr].net.pkgopt.to_2sec++; - return 0; + return; } } @@ -1891,9 +1908,8 @@ do_pkg (struct pkg *packet, _net_addr * addr) } switch (packet->h.typ) { - case (PKG_error): - if (do_error ((struct pkg_error *) packet, addr) < 0) - return -1; + case (PKG_error): + do_error ((struct pkg_error *) packet, addr); break; case (PKG_gameinfo): do_gameinfo ((struct pkg_gameinfo *) packet, addr); @@ -1977,6 +1993,4 @@ do_pkg (struct pkg *packet, _net_addr * addr) send_error (addr, "BomberClone: unknown data packet"); break; } - - return 0; }; diff --git a/src/pkgcache.c b/src/pkgcache.c index 16ba347..46da298 100644 --- a/src/pkgcache.c +++ b/src/pkgcache.c @@ -1,4 +1,4 @@ -/* $Id: pkgcache.c,v 1.9 2005/03/28 03:04:35 stpohle Exp $ +/* $Id: pkgcache.c,v 1.10 2006/08/13 21:26:50 stpohle Exp $ * Resendcache work, We need this to resend lost packets over the network. * we will keep every packet with the PKGF_ackreq flag as long as we haven't * got any answer from the destination host. And resend the packet after a givin @@ -10,162 +10,100 @@ #include "network.h" #include "packets.h" -/* - set pointers at the giving pos -*/ -void -rscache_setpointer (int pos) -{ - resend_cache.entry = (struct _rscache_entry *) (((char *) resend_cache.data) + pos); -}; - - -/* - add a packet to the cache and sets the timestamp -*/ -int -rscache_add (_net_addr * addr, struct pkg *packet) -{ - int newlen; - - /* maybe we forgot to check here something? i don't know but it seems - * that i forgot to calculate the packetsize into this. - * (i'll add the packet len to this calculation) */ - if (resend_cache.fill + sizeof (struct _rscache_entry) + packet->h.len > PKG_RESENDCACHE_SIZE) - return -1; - - rscache_setpointer (resend_cache.fill); - resend_cache.entry->retry = 0; - resend_cache.entry->timestamp = timestamp; - memcpy (&resend_cache.entry->addr, addr, sizeof (_net_addr)); - memcpy (&resend_cache.entry->packet, packet, NTOH16 (packet->h.len)); +struct _resend_cache rscache; - newlen = resend_cache.fill + rscache_getcurlen (); - - resend_cache.fill = newlen; - - return 0; +/* reset the counter for the resendcache */ +void rscache_init () { + rscache.count = 0; }; -/* - deletes the packet at current pointer in the cache -*/ -void -rscache_del () -{ - int len, - size; - char *pos1; - - /* check if we are able to delete */ - if ((char *) resend_cache.data > (char *) resend_cache.entry || - (char *) resend_cache.entry > (char *) resend_cache.data + resend_cache.fill || - resend_cache.fill == -1 || resend_cache.data == NULL) { - d_printf ("rscache_del: something wrong with the cache\n"); - exit (1); - return; - } - - /* newlen = size of the cacheentry we are going to delete */ - len = rscache_getcurlen (); +/* add a new packet to the list - if (resend_cache.fill <= len) /* something wrong?, fill is smaler as the cacheentry, delete the cache */ - resend_cache.fill = 0; - else { - pos1 = (char *) resend_cache.entry + len; - size = PKG_RESENDCACHE_SIZE - (pos1 - resend_cache.data); +struct _rscache_entry { + Uint32 timestamp; // pointer to the timestamp + signed char retry; // retry's how many times we tryed this + _net_addr addr; // the address + char packet[MAX_UDPDATA]; // the packet +} __attribute__((packed)); - if (resend_cache.fill < PKG_RESENDCACHE_SIZE) { - memmove (resend_cache.entry, pos1, size); - resend_cache.fill = resend_cache.fill - len; - } - } -}; - -/* - get the position in the cache where our needed packet is */ -int -rscache_getpos (_net_addr * addr, unsigned char typ, short int id) -{ - int len, - pos, - done = 0; - - for (pos = 0; (pos < resend_cache.fill && done == 0);) { - - rscache_setpointer (pos); - - /* get size of the cacheentry */ - len = rscache_getcurlen (); - - if (strcmp (addr->host, resend_cache.entry->addr.host) == 0 && - strcmp (addr->port, resend_cache.entry->addr.port) == 0 && - typ == resend_cache.entry->packet.h.typ && id == NTOH16 (resend_cache.entry->packet.h.id)) - done = 1; /* we have found the old packet */ - else - pos = pos + len; - } - - if (done == 0) /* we have found nothing */ - return -1; - - return pos; +void rscache_add (_net_addr *addr, struct pkg *packet) { + int len; + + d_printf ("rscache_add: addr %p, pkg %p\n", addr, packet); + /* check if there is still some free space left. */ + if (rscache.count >= PKG_RESENDCACHE_SIZE) { + d_printf ("rscache_add no free rscache entry left.\n"); + return; + } + + /* copy all the data we need. */ + rscache.entry[rscache.count].timestamp = timestamp; + rscache.entry[rscache.count].retry = 0; + memcpy (&rscache.entry[rscache.count].addr, addr, sizeof (_net_addr)); + len = NTOH16 (packet->h.len); + if (MAX_UDPDATA < len) len = MAX_UDPDATA; + memcpy (&rscache.entry[rscache.count].packet, packet, MAX_UDPDATA); + rscache.count ++; }; -/* get the len of the current entry */ -int -rscache_getcurlen () -{ - int len; - - len = sizeof (struct _rscache_entry) - sizeof (struct pkg) + NTOH16 (resend_cache.entry->packet.h.len); - return len; +/* delete the packet from the cache */ +void rscache_del (_net_addr *addr, unsigned char typ, short unsigned int id) { + int i; + + d_printf ("rscache_del: addr %p\n", addr); + + for (i = 0; (i < rscache.count) && (i < PKG_RESENDCACHE_SIZE); i++) { + if (rscache.entry[i].addr.pl_nr == addr->pl_nr && + NTOH16(rscache.entry[i].packet.h.id) == id && + ((struct pkg)rscache.entry[i].packet).h.typ == typ) { // found element + int a; + + for (a = i; a < rscache.count - 1; a++) + rscache.entry[i] = rscache.entry[i+1]; + rscache.count--; + break; + } + } }; - -/* - the loop for the cache.. to see what will have to be resend -*/ -void -rscache_loop () -{ - int len, - pos, - timeout; +/* test for old packets where we haven't got a ackreq packet for. + * If the timeout is up resend the packet again until RESENDCACHE_RETRY + * has reached then delete the packet. */ +void rscache_loop () { + int i; + int timeout; + if (bman.state==GS_running) timeout = RESENDCACHE_TIMEOUT; else timeout=RESENDCACHE_TIMEOUT_MENU; - for (pos = 0; pos < resend_cache.fill && pos < PKG_RESENDCACHE_SIZE && pos >= 0;) { - - rscache_setpointer (pos); - len = rscache_getcurlen (); - if (timestamp - resend_cache.entry->timestamp >= timeout - && resend_cache.entry->retry < RESENDCACHE_RETRY) { + for (i = 0; (i < rscache.count) && (i < PKG_RESENDCACHE_SIZE); i++) { + if (timestamp - rscache.entry[i].timestamp >= timeout + && rscache.entry[i].retry < RESENDCACHE_RETRY) { /* send it again */ d_printf ("Data Send Timeout (%s:%s) Resend now Package Fill %d, Pos %d\n", - resend_cache.entry->addr.host, resend_cache.entry->addr.port, resend_cache.fill,pos); - udp_send (bman.sock, (char *) &resend_cache.entry->packet, - NTOH16 (resend_cache.entry->packet.h.len), &resend_cache.entry->addr.sAddr, - bman.net_ai_family); - resend_cache.entry->timestamp = timestamp; - resend_cache.entry->retry++; - if (resend_cache.entry->addr.pl_nr >= 0 && resend_cache.entry->addr.pl_nr < MAX_PLAYERS) - players[resend_cache.entry->addr.pl_nr].net.pkgopt.to_2sec++; + rscache.entry[i].addr.host, rscache.entry[i].addr.port, rscache.count,i); + + udp_send (bman.sock, (char *) &rscache.entry[i].packet, + NTOH16 (rscache.entry[i].packet.h.len), + &rscache.entry[i].addr.sAddr, + bman.net_ai_family); + rscache.entry[i].timestamp = timestamp; + rscache.entry[i].retry++; + if (rscache.entry[i].addr.pl_nr >= 0 && rscache.entry[i].addr.pl_nr < MAX_PLAYERS) + players[rscache.entry[i].addr.pl_nr].net.pkgopt.to_2sec++; } - if (timestamp - resend_cache.entry->timestamp >= timeout - && resend_cache.entry->retry >= RESENDCACHE_RETRY) { + if (timestamp - rscache.entry[i].timestamp >= timeout + && rscache.entry[i].retry >= RESENDCACHE_RETRY) { d_printf ("Data Send Timeout (%s:%s) Delete now Package Fill %d, Pos %d\n", - resend_cache.entry->addr.host, resend_cache.entry->addr.port, - resend_cache.fill, pos); - if (resend_cache.entry->addr.pl_nr >= 0 && resend_cache.entry->addr.pl_nr < MAX_PLAYERS) - players[resend_cache.entry->addr.pl_nr].net.pkgopt.to_2sec++; + rscache.entry[i].addr.host, rscache.entry[i].addr.port, rscache.count, i); + if (rscache.entry[i].addr.pl_nr >= 0 && rscache.entry[i].addr.pl_nr < MAX_PLAYERS) + players[rscache.entry[i].addr.pl_nr].net.pkgopt.to_2sec++; - rscache_del (); + rscache_del (&rscache.entry[i].addr, rscache.entry[i].packet.h.typ, + NTOH16(rscache.entry[i].packet.h.id)); } - else - pos = pos + len; - } + } };