3 * Various SNAC-related dodads...
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.
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.
19 * Called from aim_session_init() to initialize the hash.
21 faim_internal void aim_initsnachash(aim_session_t *sess)
25 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++)
26 sess->snac_hash[i] = NULL;
31 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)
35 snac.id = sess->snacid_next++;
41 if (!(snac.data = malloc(datalen)))
43 memcpy(snac.data, data, datalen);
47 return aim_newsnac(sess, &snac);
51 * Clones the passed snac structure and caches it in the
54 faim_internal aim_snacid_t aim_newsnac(aim_session_t *sess, aim_snac_t *newsnac)
62 if (!(snac = malloc(sizeof(aim_snac_t))))
64 memcpy(snac, newsnac, sizeof(aim_snac_t));
65 snac->issuetime = time(NULL);
67 index = snac->id % FAIM_SNAC_HASH_SIZE;
69 snac->next = (aim_snac_t *)sess->snac_hash[index];
70 sess->snac_hash[index] = (void *)snac;
76 * Finds a snac structure with the passed SNAC ID,
77 * removes it from the list/hash, and returns a pointer to it.
79 * The returned structure must be freed by the caller.
82 faim_internal aim_snac_t *aim_remsnac(aim_session_t *sess, aim_snacid_t id)
84 aim_snac_t *cur, **prev;
87 index = id % FAIM_SNAC_HASH_SIZE;
89 for (prev = (aim_snac_t **)&sess->snac_hash[index]; (cur = *prev); ) {
101 * This is for cleaning up old SNACs that either don't get replies or
102 * a reply was never received for. Garabage collection. Plain and simple.
104 * maxage is the _minimum_ age in seconds to keep SNACs.
107 faim_internal void aim_cleansnacs(aim_session_t *sess, int maxage)
111 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
112 aim_snac_t *cur, **prev;
115 if (!sess->snac_hash[i])
118 curtime = time(NULL); /* done here in case we waited for the lock */
120 for (prev = (aim_snac_t **)&sess->snac_hash[i]; (cur = *prev); ) {
121 if ((curtime - cur->issuetime) > maxage) {
125 /* XXX should we have destructors here? */
137 faim_internal int aim_putsnac(aim_bstream_t *bs, fu16_t family, fu16_t subtype, fu16_t flags, aim_snacid_t snacid)
140 aimbs_put16(bs, family);
141 aimbs_put16(bs, subtype);
142 aimbs_put16(bs, flags);
143 aimbs_put32(bs, snacid);