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