| 1 /* |
|
| 2 * Gaim's oscar protocol plugin |
|
| 3 * This file is the legal property of its developers. |
|
| 4 * Please see the AUTHORS file distributed alongside this file. |
|
| 5 * |
|
| 6 * This library is free software; you can redistribute it and/or |
|
| 7 * modify it under the terms of the GNU Lesser General Public |
|
| 8 * License as published by the Free Software Foundation; either |
|
| 9 * version 2 of the License, or (at your option) any later version. |
|
| 10 * |
|
| 11 * This library is distributed in the hope that it will be useful, |
|
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 14 * Lesser General Public License for more details. |
|
| 15 * |
|
| 16 * You should have received a copy of the GNU Lesser General Public |
|
| 17 * License along with this library; if not, write to the Free Software |
|
| 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
| 19 */ |
|
| 20 |
|
| 21 /* |
|
| 22 * |
|
| 23 * Various SNAC-related dodads... |
|
| 24 * |
|
| 25 * outstanding_snacs is a list of aim_snac_t structs. A SNAC should be added |
|
| 26 * whenever a new SNAC is sent and it should remain in the list until the |
|
| 27 * response for it has been received. |
|
| 28 * |
|
| 29 * cleansnacs() should be called periodically by the client in order |
|
| 30 * to facilitate the aging out of unreplied-to SNACs. This can and does |
|
| 31 * happen, so it should be handled. |
|
| 32 * |
|
| 33 */ |
|
| 34 |
|
| 35 #include "oscar.h" |
|
| 36 |
|
| 37 /* |
|
| 38 * Called from oscar_session_new() to initialize the hash. |
|
| 39 */ |
|
| 40 void aim_initsnachash(OscarData *od) |
|
| 41 { |
|
| 42 int i; |
|
| 43 |
|
| 44 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) |
|
| 45 od->snac_hash[i] = NULL; |
|
| 46 |
|
| 47 return; |
|
| 48 } |
|
| 49 |
|
| 50 aim_snacid_t aim_cachesnac(OscarData *od, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen) |
|
| 51 { |
|
| 52 aim_snac_t snac; |
|
| 53 |
|
| 54 snac.id = od->snacid_next++; |
|
| 55 snac.family = family; |
|
| 56 snac.type = type; |
|
| 57 snac.flags = flags; |
|
| 58 |
|
| 59 if (datalen) { |
|
| 60 if (!(snac.data = malloc(datalen))) |
|
| 61 return 0; /* er... */ |
|
| 62 memcpy(snac.data, data, datalen); |
|
| 63 } else |
|
| 64 snac.data = NULL; |
|
| 65 |
|
| 66 return aim_newsnac(od, &snac); |
|
| 67 } |
|
| 68 |
|
| 69 /* |
|
| 70 * Clones the passed snac structure and caches it in the |
|
| 71 * list/hash. |
|
| 72 */ |
|
| 73 aim_snacid_t aim_newsnac(OscarData *od, aim_snac_t *newsnac) |
|
| 74 { |
|
| 75 aim_snac_t *snac; |
|
| 76 int index; |
|
| 77 |
|
| 78 if (!newsnac) |
|
| 79 return 0; |
|
| 80 |
|
| 81 if (!(snac = malloc(sizeof(aim_snac_t)))) |
|
| 82 return 0; |
|
| 83 memcpy(snac, newsnac, sizeof(aim_snac_t)); |
|
| 84 snac->issuetime = time(NULL); |
|
| 85 |
|
| 86 index = snac->id % FAIM_SNAC_HASH_SIZE; |
|
| 87 |
|
| 88 snac->next = (aim_snac_t *)od->snac_hash[index]; |
|
| 89 od->snac_hash[index] = (void *)snac; |
|
| 90 |
|
| 91 return snac->id; |
|
| 92 } |
|
| 93 |
|
| 94 /* |
|
| 95 * Finds a snac structure with the passed SNAC ID, |
|
| 96 * removes it from the list/hash, and returns a pointer to it. |
|
| 97 * |
|
| 98 * The returned structure must be freed by the caller. |
|
| 99 * |
|
| 100 */ |
|
| 101 aim_snac_t *aim_remsnac(OscarData *od, aim_snacid_t id) |
|
| 102 { |
|
| 103 aim_snac_t *cur, **prev; |
|
| 104 int index; |
|
| 105 |
|
| 106 index = id % FAIM_SNAC_HASH_SIZE; |
|
| 107 |
|
| 108 for (prev = (aim_snac_t **)&od->snac_hash[index]; (cur = *prev); ) { |
|
| 109 if (cur->id == id) { |
|
| 110 *prev = cur->next; |
|
| 111 if (cur->flags & AIM_SNACFLAGS_DESTRUCTOR) { |
|
| 112 free(cur->data); |
|
| 113 cur->data = NULL; |
|
| 114 } |
|
| 115 return cur; |
|
| 116 } else |
|
| 117 prev = &cur->next; |
|
| 118 } |
|
| 119 |
|
| 120 return cur; |
|
| 121 } |
|
| 122 |
|
| 123 /* |
|
| 124 * This is for cleaning up old SNACs that either don't get replies or |
|
| 125 * a reply was never received for. Garbage collection. Plain and simple. |
|
| 126 * |
|
| 127 * maxage is the _minimum_ age in seconds to keep SNACs. |
|
| 128 * |
|
| 129 */ |
|
| 130 void aim_cleansnacs(OscarData *od, int maxage) |
|
| 131 { |
|
| 132 int i; |
|
| 133 |
|
| 134 for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) { |
|
| 135 aim_snac_t *cur, **prev; |
|
| 136 time_t curtime; |
|
| 137 |
|
| 138 if (!od->snac_hash[i]) |
|
| 139 continue; |
|
| 140 |
|
| 141 curtime = time(NULL); /* done here in case we waited for the lock */ |
|
| 142 |
|
| 143 for (prev = (aim_snac_t **)&od->snac_hash[i]; (cur = *prev); ) { |
|
| 144 if ((curtime - cur->issuetime) > maxage) { |
|
| 145 |
|
| 146 *prev = cur->next; |
|
| 147 |
|
| 148 free(cur->data); |
|
| 149 free(cur); |
|
| 150 } else |
|
| 151 prev = &cur->next; |
|
| 152 } |
|
| 153 } |
|
| 154 |
|
| 155 return; |
|
| 156 } |
|
| 157 |
|
| 158 int aim_putsnac(ByteStream *bs, guint16 family, guint16 subtype, guint16 flags, aim_snacid_t snacid) |
|
| 159 { |
|
| 160 |
|
| 161 byte_stream_put16(bs, family); |
|
| 162 byte_stream_put16(bs, subtype); |
|
| 163 byte_stream_put16(bs, flags); |
|
| 164 byte_stream_put32(bs, snacid); |
|
| 165 |
|
| 166 return 10; |
|
| 167 } |
|