summaryrefslogtreecommitdiff
path: root/libpurple/protocols/oscar/snac.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpurple/protocols/oscar/snac.c')
-rw-r--r--libpurple/protocols/oscar/snac.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/libpurple/protocols/oscar/snac.c b/libpurple/protocols/oscar/snac.c
new file mode 100644
index 0000000000..82af41b78d
--- /dev/null
+++ b/libpurple/protocols/oscar/snac.c
@@ -0,0 +1,167 @@
+/*
+ * Gaim's oscar protocol plugin
+ * This file is the legal property of its developers.
+ * Please see the AUTHORS file distributed alongside this file.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ *
+ * Various SNAC-related dodads...
+ *
+ * outstanding_snacs is a list of aim_snac_t structs. A SNAC should be added
+ * whenever a new SNAC is sent and it should remain in the list until the
+ * response for it has been received.
+ *
+ * cleansnacs() should be called periodically by the client in order
+ * to facilitate the aging out of unreplied-to SNACs. This can and does
+ * happen, so it should be handled.
+ *
+ */
+
+#include "oscar.h"
+
+/*
+ * Called from oscar_session_new() to initialize the hash.
+ */
+void aim_initsnachash(OscarData *od)
+{
+ int i;
+
+ for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++)
+ od->snac_hash[i] = NULL;
+
+ return;
+}
+
+aim_snacid_t aim_cachesnac(OscarData *od, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen)
+{
+ aim_snac_t snac;
+
+ snac.id = od->snacid_next++;
+ snac.family = family;
+ snac.type = type;
+ snac.flags = flags;
+
+ if (datalen) {
+ if (!(snac.data = malloc(datalen)))
+ return 0; /* er... */
+ memcpy(snac.data, data, datalen);
+ } else
+ snac.data = NULL;
+
+ return aim_newsnac(od, &snac);
+}
+
+/*
+ * Clones the passed snac structure and caches it in the
+ * list/hash.
+ */
+aim_snacid_t aim_newsnac(OscarData *od, aim_snac_t *newsnac)
+{
+ aim_snac_t *snac;
+ int index;
+
+ if (!newsnac)
+ return 0;
+
+ if (!(snac = malloc(sizeof(aim_snac_t))))
+ return 0;
+ memcpy(snac, newsnac, sizeof(aim_snac_t));
+ snac->issuetime = time(NULL);
+
+ index = snac->id % FAIM_SNAC_HASH_SIZE;
+
+ snac->next = (aim_snac_t *)od->snac_hash[index];
+ od->snac_hash[index] = (void *)snac;
+
+ return snac->id;
+}
+
+/*
+ * Finds a snac structure with the passed SNAC ID,
+ * removes it from the list/hash, and returns a pointer to it.
+ *
+ * The returned structure must be freed by the caller.
+ *
+ */
+aim_snac_t *aim_remsnac(OscarData *od, aim_snacid_t id)
+{
+ aim_snac_t *cur, **prev;
+ int index;
+
+ index = id % FAIM_SNAC_HASH_SIZE;
+
+ for (prev = (aim_snac_t **)&od->snac_hash[index]; (cur = *prev); ) {
+ if (cur->id == id) {
+ *prev = cur->next;
+ if (cur->flags & AIM_SNACFLAGS_DESTRUCTOR) {
+ free(cur->data);
+ cur->data = NULL;
+ }
+ return cur;
+ } else
+ prev = &cur->next;
+ }
+
+ return cur;
+}
+
+/*
+ * This is for cleaning up old SNACs that either don't get replies or
+ * a reply was never received for. Garbage collection. Plain and simple.
+ *
+ * maxage is the _minimum_ age in seconds to keep SNACs.
+ *
+ */
+void aim_cleansnacs(OscarData *od, int maxage)
+{
+ int i;
+
+ for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
+ aim_snac_t *cur, **prev;
+ time_t curtime;
+
+ if (!od->snac_hash[i])
+ continue;
+
+ curtime = time(NULL); /* done here in case we waited for the lock */
+
+ for (prev = (aim_snac_t **)&od->snac_hash[i]; (cur = *prev); ) {
+ if ((curtime - cur->issuetime) > maxage) {
+
+ *prev = cur->next;
+
+ free(cur->data);
+ free(cur);
+ } else
+ prev = &cur->next;
+ }
+ }
+
+ return;
+}
+
+int aim_putsnac(ByteStream *bs, guint16 family, guint16 subtype, guint16 flags, aim_snacid_t snacid)
+{
+
+ byte_stream_put16(bs, family);
+ byte_stream_put16(bs, subtype);
+ byte_stream_put16(bs, flags);
+ byte_stream_put32(bs, snacid);
+
+ return 10;
+}