test version with the fixed bugs found by Luigi Auriemma

origin
stpohle 19 years ago
parent c7743b0538
commit 072107d037

@ -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

@ -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

@ -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 {

@ -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;

@ -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

@ -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 <SDL.h>
@ -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;

@ -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);
};

@ -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,8 +133,7 @@ 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);

@ -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;
}
@ -614,27 +617,29 @@ send_servermode (_net_addr * addr, int pl_nr)
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;
}
}
@ -1892,8 +1909,7 @@ 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;
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;
};

@ -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;
struct _resend_cache rscache;
/* 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));
/* reset the counter for the resendcache */
void rscache_init () {
rscache.count = 0;
};
newlen = resend_cache.fill + rscache_getcurlen ();
/* add a new packet to the list
resend_cache.fill = newlen;
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));
return 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 ();
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);
if (resend_cache.fill < PKG_RESENDCACHE_SIZE) {
memmove (resend_cache.entry, pos1, size);
resend_cache.fill = resend_cache.fill - len;
}
}
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 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 ();
/* delete the packet from the cache */
void rscache_del (_net_addr *addr, unsigned char typ, short unsigned int id) {
int i;
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;
}
d_printf ("rscache_del: addr %p\n", addr);
if (done == 0) /* we have found nothing */
return -1;
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;
return pos;
for (a = i; a < rscache.count - 1; a++)
rscache.entry[i] = rscache.entry[i+1];
rscache.count--;
break;
}
}
};
/* get the len of the current entry */
int
rscache_getcurlen ()
{
int len;
/* 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;
len = sizeof (struct _rscache_entry) - sizeof (struct pkg) + NTOH16 (resend_cache.entry->packet.h.len);
return len;
};
/*
the loop for the cache.. to see what will have to be resend
*/
void
rscache_loop ()
{
int len,
pos,
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;
}
}
};

Loading…
Cancel
Save