]> andersk Git - libfaim.git/blob - src/snac.c
- Mon Sep 3 18:48:26 PDT 2001
[libfaim.git] / src / snac.c
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  */
21 faim_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                 faim_mutex_init(&sess->snac_hash_locks[i]);
28         }
29
30         return;
31 }
32
33 faim_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)
34 {
35         aim_snac_t snac;
36
37         snac.id = sess->snacid_next++;
38         snac.family = family;
39         snac.type = type;
40         snac.flags = flags;
41
42         if (datalen) {
43                 if (!(snac.data = malloc(datalen)))
44                         return 0; /* er... */
45                 memcpy(snac.data, data, datalen);
46         } else
47                 snac.data = NULL;
48
49         return aim_newsnac(sess, &snac);
50 }
51
52 /*
53  * Clones the passed snac structure and caches it in the
54  * list/hash.
55  */
56 faim_internal aim_snacid_t aim_newsnac(aim_session_t *sess, aim_snac_t *newsnac)
57 {
58         aim_snac_t *snac;
59         int index;
60
61         if (!newsnac)
62                 return 0;
63
64         if (!(snac = malloc(sizeof(aim_snac_t))))
65                 return 0;
66         memcpy(snac, newsnac, sizeof(aim_snac_t));
67         snac->issuetime = time(NULL);
68
69         index = snac->id % FAIM_SNAC_HASH_SIZE;
70
71         faim_mutex_lock(&sess->snac_hash_locks[index]);
72         snac->next = (aim_snac_t *)sess->snac_hash[index];
73         sess->snac_hash[index] = (void *)snac;
74         faim_mutex_unlock(&sess->snac_hash_locks[index]);
75
76         return snac->id;
77 }
78
79 /*
80  * Finds a snac structure with the passed SNAC ID, 
81  * removes it from the list/hash, and returns a pointer to it.
82  *
83  * The returned structure must be freed by the caller.
84  *
85  */
86 faim_internal aim_snac_t *aim_remsnac(aim_session_t *sess, aim_snacid_t id) 
87 {
88         aim_snac_t *cur, **prev;
89         int index;
90
91         index = id % FAIM_SNAC_HASH_SIZE;
92
93         faim_mutex_lock(&sess->snac_hash_locks[index]);
94         for (prev = (aim_snac_t **)&sess->snac_hash[index]; (cur = *prev); ) {
95                 if (cur->id == id) {
96                         *prev = cur->next;
97                         return cur;
98                 } else
99                         prev = &cur->next;
100         }
101         faim_mutex_unlock(&sess->snac_hash_locks[index]);
102
103         return cur;
104 }
105
106 /*
107  * This is for cleaning up old SNACs that either don't get replies or
108  * a reply was never received for.  Garabage collection. Plain and simple.
109  *
110  * maxage is the _minimum_ age in seconds to keep SNACs.
111  *
112  */
113 faim_internal void aim_cleansnacs(aim_session_t *sess, int maxage)
114 {
115         int i;
116
117         for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
118                 aim_snac_t *cur, **prev;
119                 time_t curtime;
120
121                 faim_mutex_lock(&sess->snac_hash_locks[i]);
122                 if (!sess->snac_hash[i]) {
123                         faim_mutex_unlock(&sess->snac_hash_locks[i]);
124                         continue;
125                 }
126
127                 curtime = time(NULL); /* done here in case we waited for the lock */
128
129                 for (prev = (aim_snac_t **)&sess->snac_hash[i]; (cur = *prev); ) {
130                         if ((curtime - cur->issuetime) > maxage) {
131
132                                 *prev = cur->next;
133
134                                 /* XXX should we have destructors here? */
135                                 free(cur->data);
136                                 free(cur);
137
138                         } else
139                                 prev = &cur->next;
140                 }
141                 faim_mutex_unlock(&sess->snac_hash_locks[i]);
142         }
143
144         return;
145 }
146
147 faim_internal int aim_putsnac(aim_bstream_t *bs, fu16_t family, fu16_t subtype, fu16_t flags, aim_snacid_t snacid)
148 {
149
150         aimbs_put16(bs, family);
151         aimbs_put16(bs, subtype);
152         aimbs_put16(bs, flags);
153         aimbs_put32(bs, snacid);
154
155         return 10;
156 }
This page took 0.049987 seconds and 5 git commands to generate.