source: libfaim/snac.c @ f4d0975

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since f4d0975 was 862371b, checked in by James M. Kretchmar <kretch@mit.edu>, 21 years ago
*** empty log message ***
  • Property mode set to 100644
File size: 4.0 KB
Line 
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
7 * response for it has been receieved. 
8 *
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.
12 *
13 */
14
15#define FAIM_INTERNAL
16#include <aim.h>
17
18/*
19 * Called from aim_session_init() to initialize the hash.
20 */
21faim_internal void aim_initsnachash(aim_session_t *sess)
22{
23        int i;
24
25        for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++)
26                sess->snac_hash[i] = NULL;
27
28        return;
29}
30
31faim_internal aim_snacid_t aim_cachesnac(aim_session_t *sess, const fu16_t family, const fu16_t type, const fu16_t flags, const void *data, const int datalen)
32{
33        aim_snac_t snac;
34
35        snac.id = sess->snacid_next++;
36        snac.family = family;
37        snac.type = type;
38        snac.flags = flags;
39
40        if (datalen) {
41                if (!(snac.data = malloc(datalen)))
42                        return 0; /* er... */
43                memcpy(snac.data, data, datalen);
44        } else
45                snac.data = NULL;
46
47        return aim_newsnac(sess, &snac);
48}
49
50/*
51 * Clones the passed snac structure and caches it in the
52 * list/hash.
53 */
54faim_internal aim_snacid_t aim_newsnac(aim_session_t *sess, aim_snac_t *newsnac)
55{
56        aim_snac_t *snac;
57        int index;
58
59        if (!newsnac)
60                return 0;
61
62        if (!(snac = malloc(sizeof(aim_snac_t))))
63                return 0;
64        memcpy(snac, newsnac, sizeof(aim_snac_t));
65        snac->issuetime = time(NULL);
66
67        index = snac->id % FAIM_SNAC_HASH_SIZE;
68
69        snac->next = (aim_snac_t *)sess->snac_hash[index];
70        sess->snac_hash[index] = (void *)snac;
71
72        return snac->id;
73}
74
75/*
76 * Finds a snac structure with the passed SNAC ID,
77 * removes it from the list/hash, and returns a pointer to it.
78 *
79 * The returned structure must be freed by the caller.
80 *
81 */
82faim_internal aim_snac_t *aim_remsnac(aim_session_t *sess, aim_snacid_t id) 
83{
84        aim_snac_t *cur, **prev;
85        int index;
86
87        index = id % FAIM_SNAC_HASH_SIZE;
88
89        for (prev = (aim_snac_t **)&sess->snac_hash[index]; (cur = *prev); ) {
90                if (cur->id == id) {
91                        *prev = cur->next;
92                        if (cur->flags & AIM_SNACFLAGS_DESTRUCTOR) {
93                                struct aim_snac_destructor *asd = cur->data;
94                                cur->data = asd->data;
95                                free(asd);
96                        }
97                        return cur;
98                } else
99                        prev = &cur->next;
100        }
101
102        return cur;
103}
104
105/* Free a SNAC, and call the appropriate destructor if necessary.
106 */
107faim_internal faim_shortfunc void aim_cleansnac(aim_session_t *sess, aim_snac_t *snac)
108{
109        aim_module_t *cur;
110
111        if (snac->flags & AIM_SNACFLAGS_DESTRUCTOR) {
112                struct aim_snac_destructor *d = snac->data;
113                aim_modsnac_t modsnac;
114
115                modsnac.id = snac->id;
116                modsnac.subtype = snac->type;
117                modsnac.family = snac->family;
118                modsnac.flags = snac->flags;
119
120                for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next)
121                {
122                        if (!cur->snacdestructor)
123                                continue;
124                        if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) &&
125                                (cur->family != modsnac.family))
126                                continue;
127                        if (cur->snacdestructor(sess, d->conn, &modsnac,
128                                                d->data))
129                                break;
130                }
131                free(d->data);
132        }
133
134        free(snac->data);
135        free(snac);
136}
137
138
139/*
140 * This is for cleaning up old SNACs that either don't get replies or
141 * a reply was never received for.  Garabage collection. Plain and simple.
142 *
143 * maxage is the _minimum_ age in seconds to keep SNACs.
144 *
145 */
146faim_internal void aim_cleansnacs(aim_session_t *sess, int maxage)
147{
148        int i;
149
150        for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
151                aim_snac_t *cur, **prev;
152                time_t curtime;
153
154                if (!sess->snac_hash[i])
155                        continue;
156
157                curtime = time(NULL); /* done here in case we waited for the lock */
158
159                for (prev = (aim_snac_t **)&sess->snac_hash[i]; (cur = *prev); ) {
160                        if ((curtime - cur->issuetime) > maxage) {
161
162                                *prev = cur->next;
163
164                                aim_cleansnac(sess, cur);
165                        } else
166                                prev = &cur->next;
167                }
168        }
169
170        return;
171}
172
173faim_internal int aim_putsnac(aim_bstream_t *bs, fu16_t family, fu16_t subtype, fu16_t flags, aim_snacid_t snacid)
174{
175
176        aimbs_put16(bs, family);
177        aimbs_put16(bs, subtype);
178        aimbs_put16(bs, flags);
179        aimbs_put32(bs, snacid);
180
181        return 10;
182}
Note: See TracBrowser for help on using the repository browser.