1 /* $Id: pkgcache.c,v 1.14 2009-05-11 20:51:25 stpohle Exp $
2  * Resendcache work, We need this to resend lost packets over the network.
3  * we will keep every packet with the PKGF_ackreq flag as long as we haven't
4  * got any answer from the destination host. And resend the packet after a givin
5  * time. The maximum time for a resend is 10 times if we haven't got any reply
6  * by then we delete the packet from the cache. By doing this the game will not
7  * anymore sync. with all clients.
8  */
9 #include "bomberclone.h"
10 #include "network.h"
11 #include "packets.h"
12 
13 struct _resend_cache rscache;
14 
15 /* reset the counter for the resendcache */
rscache_init()16 void rscache_init () {
17 	rscache.count = 0;
18 };
19 
20 /* add a new packet to the list */
rscache_add(_net_addr * addr,struct pkg * packet)21 void rscache_add (_net_addr *addr, struct pkg *packet) {
22 	int len;
23 
24 	// d_printf ("rscache_add: pl:%p, typ:%u id:%u\n", addr->pl_nr, packet->h.typ, packet->h.id);
25 	/* check if there is still some free space left. */
26 	if (rscache.count >= PKG_RESENDCACHE_SIZE) {
27 		d_printf ("rscache_add no free rscache entry left.\n");
28 		return;
29 	}
30 
31 	/* copy all the data we need. */
32 	rscache.entry[rscache.count].timestamp = timestamp;
33 	rscache.entry[rscache.count].retry = 0;
34 	memcpy (&rscache.entry[rscache.count].addr, addr, sizeof (_net_addr));
35 	len = NTOH16 (packet->h.len);
36 	if (MAX_UDPDATA < len) len = MAX_UDPDATA;
37 	memcpy (&rscache.entry[rscache.count].packet, packet, MAX_UDPDATA);
38 	rscache.count ++;
39 };
40 
41 /* delete the entry */
rscache_delnr(int nr)42 void rscache_delnr (int nr) {
43 	int a;
44 
45 	if (nr >= 0 && nr < PKG_RESENDCACHE_SIZE) {
46 		for (a = nr; a < rscache.count - 1; a++)
47 			rscache.entry[a] = rscache.entry[a+1];
48 		rscache.count--;
49 		d_printf ("rscache_delnr: element %d deleted.\n", nr);
50 	}
51 	else
52 		d_printf ("rscache_delnr: number is out of range (%d)\n", nr);
53 }
54 
55 
56 /* find and delete the givin packet.
57  * Return Value: 0 = nothing deleted, 1 one entry deleted */
rscache_del(_net_addr * addr,unsigned char typ,short unsigned int id)58 int rscache_del (_net_addr *addr, unsigned char typ, short unsigned int id) {
59 	int i;
60 
61 	 // d_printf ("rscache_del: addr %p (pl_nr:%d, typ:%d, id:%u\n", addr, addr->pl_nr, typ, id);
62 
63 	for (i = 0; (i < rscache.count) && (i < PKG_RESENDCACHE_SIZE); i++) {
64 		if (rscache.entry[i].addr.pl_nr == addr->pl_nr &&
65 			NTOH16(rscache.entry[i].packet.h.id) == id &&
66 			rscache.entry[i].packet.h.typ == typ) { // found element
67 				rscache_delnr (i);
68 				return 1;
69 		}
70 	}
71 	return 0;
72 };
73 
74 /* test for old packets where we haven't got a ackreq packet for.
75  * If the timeout is up resend the packet again until RESENDCACHE_RETRY
76  * has reached then delete the packet. */
rscache_loop()77 void rscache_loop () {
78 	int i;
79 	int timeout;
80 
81 	if (bman.state==GS_running) timeout = RESENDCACHE_TIMEOUT; else timeout=RESENDCACHE_TIMEOUT_MENU;
82 
83 	for (i = 0; (i < rscache.count) && (i < PKG_RESENDCACHE_SIZE); i++) {
84         if (timestamp - rscache.entry[i].timestamp >= timeout
85             && rscache.entry[i].retry < RESENDCACHE_RETRY) {
86             /* send it again */
87             d_printf
88                 ("Data Send Timeout Resend pl:%p, typ:%u id:%u Fill:%d Pos:%d\n",
89                 rscache.entry[i].addr.pl_nr, rscache.entry[i].packet.h.typ, rscache.entry[i].packet.h.id, rscache.count, i);
90 
91             udp_send (bman.sock, (char *) &rscache.entry[i].packet,
92             			NTOH16 (rscache.entry[i].packet.h.len),
93 						&rscache.entry[i].addr.sAddr,
94             			bman.net_ai_family);
95             rscache.entry[i].timestamp = timestamp;
96             rscache.entry[i].retry++;
97             if (rscache.entry[i].addr.pl_nr >= 0 && rscache.entry[i].addr.pl_nr < MAX_PLAYERS)
98 				players[rscache.entry[i].addr.pl_nr].net.pkgopt.to_2sec++;
99         }
100 
101         if (timestamp - rscache.entry[i].timestamp >= timeout
102             && rscache.entry[i].retry >= RESENDCACHE_RETRY) {
103             d_printf
104                 ("Data Send Timeout Delete pl:%p, typ:%u id:%u Fill:%d Pos:%d\n",
105                 rscache.entry[i].addr.pl_nr, rscache.entry[i].packet.h.typ, rscache.entry[i].packet.h.id, rscache.count, i);
106             if (rscache.entry[i].addr.pl_nr >= 0 && rscache.entry[i].addr.pl_nr < MAX_PLAYERS)
107 				players[rscache.entry[i].addr.pl_nr].net.pkgopt.to_2sec++;
108 
109             rscache_delnr (i);
110 			if (i > 0) i--;
111         }
112 	}
113 };
114