]> andersk Git - libfaim.git/blame - aim_snac.c
- Thu Feb 8 02:31:25 UTC 2001
[libfaim.git] / aim_snac.c
CommitLineData
9de3ca7e 1/*
2 *
3 * Various SNAC-related dodads...
4 *
5 * outstanding_snacs is a list of aim_snac_t structs. A SNAC should be added
6 * whenever a new SNAC is sent and it should remain in the list until the
b13c9e13 7 * response for it has been receieved.
9de3ca7e 8 *
b13c9e13 9 * cleansnacs() should be called periodically by the client in order
10 * to facilitate the aging out of unreplied-to SNACs. This can and does
11 * happen, so it should be handled.
9de3ca7e 12 *
13 */
14
37ee990e 15#define FAIM_INTERNAL
a25832e6 16#include <faim/aim.h>
9de3ca7e 17
b13c9e13 18/*
19 * Called from aim_session_init() to initialize the hash.
20 */
c5ca2538 21faim_internal void aim_initsnachash(struct aim_session_t *sess)
b13c9e13 22{
23 int i;
24
25 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
26 sess->snac_hash[i] = NULL;
27 faim_mutex_init(&sess->snac_hash_locks[i]);
28 }
29
30 return;
31}
32
1ea867e3 33faim_internal unsigned long aim_cachesnac(struct aim_session_t *sess,
34 const unsigned short family,
35 const unsigned short type,
36 const unsigned short flags,
37 const void *data, const int datalen)
38{
39 struct aim_snac_t snac;
40
41 snac.id = sess->snac_nextid++;
42 snac.family = family;
43 snac.type = type;
44 snac.flags = flags;
45
46 snac.data = malloc(datalen);
47 memcpy(snac.data, data, datalen);
48
49 return aim_newsnac(sess, &snac);
50}
51
b13c9e13 52/*
53 * Clones the passed snac structure and caches it in the
54 * list/hash.
55 */
c5ca2538 56faim_internal unsigned long aim_newsnac(struct aim_session_t *sess,
57 struct aim_snac_t *newsnac)
a25832e6 58{
96f8b1ed 59 struct aim_snac_t *snac = NULL;
b13c9e13 60 int index;
61
a25832e6 62 if (!newsnac)
63 return 0;
9de3ca7e 64
17d80b55 65 if (!(snac = calloc(1, sizeof(struct aim_snac_t))))
a25832e6 66 return 0;
67 memcpy(snac, newsnac, sizeof(struct aim_snac_t));
68 snac->issuetime = time(&snac->issuetime);
69 snac->next = NULL;
b13c9e13 70
71 index = snac->id % FAIM_SNAC_HASH_SIZE;
72
73 faim_mutex_lock(&sess->snac_hash_locks[index]);
17d80b55 74 snac->next = sess->snac_hash[index];
75 sess->snac_hash[index] = snac;
b13c9e13 76 faim_mutex_unlock(&sess->snac_hash_locks[index]);
5b401785 77
a25832e6 78 return(snac->id);
79}
9de3ca7e 80
b13c9e13 81/*
82 * Finds a snac structure with the passed SNAC ID,
83 * removes it from the list/hash, and returns a pointer to it.
84 *
85 * The returned structure must be freed by the caller.
86 *
87 */
c5ca2538 88faim_internal struct aim_snac_t *aim_remsnac(struct aim_session_t *sess,
89 u_long id)
a25832e6 90{
96f8b1ed 91 struct aim_snac_t *cur = NULL;
b13c9e13 92 int index;
5b401785 93
b13c9e13 94 index = id % FAIM_SNAC_HASH_SIZE;
5b401785 95
b13c9e13 96 faim_mutex_lock(&sess->snac_hash_locks[index]);
97 if (!sess->snac_hash[index])
98 ;
96f8b1ed 99 else if (sess->snac_hash[index]->id == id) {
100 cur = sess->snac_hash[index];
101 sess->snac_hash[index] = cur->next;
b13c9e13 102 } else {
103 cur = sess->snac_hash[index];
104 while (cur->next) {
105 if (cur->next->id == id) {
106 struct aim_snac_t *tmp;
107
108 tmp = cur->next;
109 cur->next = cur->next->next;
110 cur = tmp;
111 break;
112 }
113 cur = cur->next;
a25832e6 114 }
a25832e6 115 }
b13c9e13 116 faim_mutex_unlock(&sess->snac_hash_locks[index]);
117
118 return cur;
9de3ca7e 119}
120
121/*
122 * This is for cleaning up old SNACs that either don't get replies or
123 * a reply was never received for. Garabage collection. Plain and simple.
124 *
b13c9e13 125 * maxage is the _minimum_ age in seconds to keep SNACs.
9de3ca7e 126 *
127 */
c5ca2538 128faim_internal int aim_cleansnacs(struct aim_session_t *sess,
129 int maxage)
9de3ca7e 130{
b13c9e13 131 int i;
132
133 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
37ee990e 134 struct aim_snac_t *cur, **prev;
53c935f8 135 time_t curtime;
136
b13c9e13 137 faim_mutex_lock(&sess->snac_hash_locks[i]);
96f8b1ed 138 if (!sess->snac_hash[i]) {
139 faim_mutex_unlock(&sess->snac_hash_locks[i]);
140 continue;
141 }
142
143 curtime = time(NULL); /* done here in case we waited for the lock */
144
37ee990e 145 for (prev = &sess->snac_hash[i]; (cur = *prev); ) {
96f8b1ed 146 if ((curtime - cur->issuetime) > maxage) {
37ee990e 147
148 *prev = cur->next;
96f8b1ed 149
96f8b1ed 150 /* XXX should we have destructors here? */
151 if (cur->data)
152 free(cur->data);
153 free(cur);
154
37ee990e 155 } else
156 prev = &cur->next;
9de3ca7e 157 }
96f8b1ed 158
b13c9e13 159 faim_mutex_unlock(&sess->snac_hash_locks[i]);
160 }
161
9de3ca7e 162 return 0;
163}
164
c5ca2538 165faim_internal int aim_putsnac(u_char *buf, int family, int subtype, int flags, u_long snacid)
9de3ca7e 166{
167 int curbyte = 0;
168 curbyte += aimutil_put16(buf+curbyte, (u_short)(family&0xffff));
169 curbyte += aimutil_put16(buf+curbyte, (u_short)(subtype&0xffff));
170 curbyte += aimutil_put16(buf+curbyte, (u_short)(flags&0xffff));
171 curbyte += aimutil_put32(buf+curbyte, snacid);
172 return curbyte;
173}
This page took 1.571588 seconds and 5 git commands to generate.