comparison src/protocols/oscar/conn.c @ 13253:87a7c3077c19

[gaim-migrate @ 15619] More cleaning up of oscar. Renamed some functions to be more clear. Got rid of some stuff that wasn't used. Inlined some small things in conn.c that were only used once. The goals of all this are 1. Non-blocking I/O for all connections 2. p2p stuff won't use the same struct as oscar connections, because that's stupid 3. The oscar PRPL should be less scary committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sun, 12 Feb 2006 21:27:04 +0000
parents 2871c385c45a
children e9802db22b06
comparison
equal deleted inserted replaced
13252:2871c385c45a 13253:87a7c3077c19
24 * Does all this gloriously nifty connection handling stuff... 24 * Does all this gloriously nifty connection handling stuff...
25 * 25 *
26 */ 26 */
27 27
28 #include "oscar.h" 28 #include "oscar.h"
29
30 /* This is defined in oscar.h, but only when !FAIM_INTERNAL, since the rest of
31 * the library is not allowed to call it. */
32 faim_export void aim_conn_kill(OscarSession *sess, OscarConnection **deadconn);
33 29
34 #ifndef _WIN32 30 #ifndef _WIN32
35 #include <netdb.h> 31 #include <netdb.h>
36 #include <sys/socket.h> 32 #include <sys/socket.h>
37 #include <netinet/in.h> 33 #include <netinet/in.h>
42 #endif 38 #endif
43 39
44 /** 40 /**
45 * In OSCAR, every connection has a set of SNAC groups associated 41 * In OSCAR, every connection has a set of SNAC groups associated
46 * with it. These are the groups that you can send over this connection 42 * with it. These are the groups that you can send over this connection
47 * without being guaranteed a "Not supported" SNAC error. 43 * without being guaranteed a "Not supported" SNAC error.
48 * 44 *
49 * The grand theory of things says that these associations transcend 45 * The grand theory of things says that these associations transcend
50 * what libfaim calls "connection types" (conn->type). You can probably 46 * what libfaim calls "connection types" (conn->type). You can probably
51 * see the elegance here, but since I want to revel in it for a bit, you 47 * see the elegance here, but since I want to revel in it for a bit, you
52 * get to hear it all spelled out. 48 * get to hear it all spelled out.
53 * 49 *
54 * So let us say that you have your core BOS connection running. One 50 * So let us say that you have your core BOS connection running. One
55 * of your modules has just given you a SNAC of the group 0x0004 to send 51 * of your modules has just given you a SNAC of the group 0x0004 to send
56 * you. Maybe an IM destined for some twit in Greenland. So you start 52 * you. Maybe an IM destined for some twit in Greenland. So you start
57 * at the top of your connection list, looking for a connection that 53 * at the top of your connection list, looking for a connection that
58 * claims to support group 0x0004. You find one. Why, that neat BOS 54 * claims to support group 0x0004. You find one. Why, that neat BOS
59 * connection of yours can do that. So you send it on its way. 55 * connection of yours can do that. So you send it on its way.
60 * 56 *
61 * Now, say, that fellow from Greenland has friends and they all want to 57 * Now, say, that fellow from Greenland has friends and they all want to
62 * meet up with you in a lame chat room. This has landed you a SNAC 58 * meet up with you in a lame chat room. This has landed you a SNAC
70 * marked the need for a connection supporting group 0x000e. A few seconds 66 * marked the need for a connection supporting group 0x000e. A few seconds
71 * later, you receive a service redirect with an IP address and a cookie in 67 * later, you receive a service redirect with an IP address and a cookie in
72 * it. Great, you say. Now I have something to do. Off you go, making 68 * it. Great, you say. Now I have something to do. Off you go, making
73 * that connection. One of the first things you get from this new server 69 * that connection. One of the first things you get from this new server
74 * is a message saying that indeed it does support the group you were looking 70 * is a message saying that indeed it does support the group you were looking
75 * for. So you continue and send rate confirmation and all that. 71 * for. So you continue and send rate confirmation and all that.
76 * 72 *
77 * Then you remember you had that SNAC to send, and now you have a means to 73 * Then you remember you had that SNAC to send, and now you have a means to
78 * do it, and you do, and everyone is happy. Except the Greenlander, who is 74 * do it, and you do, and everyone is happy. Except the Greenlander, who is
79 * still stuck in the bitter cold. 75 * still stuck in the bitter cold.
80 * 76 *
81 * Oh, and this is useful for building the Migration SNACs, too. In the 77 * Oh, and this is useful for building the Migration SNACs, too. In the
84 * 80 *
85 * Just to make me look better, I'll say that I've known about this great 81 * Just to make me look better, I'll say that I've known about this great
86 * scheme for quite some time now. But I still haven't convinced myself 82 * scheme for quite some time now. But I still haven't convinced myself
87 * to make libfaim work that way. It would take a fair amount of effort, 83 * to make libfaim work that way. It would take a fair amount of effort,
88 * and probably some client API changes as well. (Whenever I don't want 84 * and probably some client API changes as well. (Whenever I don't want
89 * to do something, I just say it would change the client API. Then I 85 * to do something, I just say it would change the client API. Then I
90 * instantly have a couple of supporters of not doing it.) 86 * instantly have a couple of supporters of not doing it.)
91 * 87 *
92 * Generally, addgroup is only called by the internal handling of the 88 * Generally, addgroup is only called by the internal handling of the
93 * server ready SNAC. So if you want to do something before that, you'll 89 * server ready SNAC. So if you want to do something before that, you'll
94 * have to be more creative. That is done rather early, though, so I don't 90 * have to be more creative. That is done rather early, though, so I don't
95 * think you have to worry about it. Unless you're me. I care deeply 91 * think you have to worry about it. Unless you're me. I care deeply
96 * about such inane things. 92 * about such inane things.
97 * 93 *
98 */ 94 */
99 faim_internal void aim_conn_addgroup(OscarConnection *conn, guint16 group) 95 void
96 aim_conn_addgroup(OscarConnection *conn, guint16 group)
100 { 97 {
101 aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; 98 aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
102 struct snacgroup *sg; 99 struct snacgroup *sg;
103 100
104 if (!(sg = malloc(sizeof(struct snacgroup)))) 101 sg = malloc(sizeof(struct snacgroup));
105 return;
106 102
107 gaim_debug_misc("oscar", "adding group 0x%04x\n", group); 103 gaim_debug_misc("oscar", "adding group 0x%04x\n", group);
108 sg->group = group; 104 sg->group = group;
109 105
110 sg->next = ins->groups; 106 sg->next = ins->groups;
111 ins->groups = sg; 107 ins->groups = sg;
112 108 }
113 return; 109
114 } 110 OscarConnection *
115 111 aim_conn_findbygroup(OscarSession *sess, guint16 group)
116 faim_export OscarConnection *aim_conn_findbygroup(OscarSession *sess, guint16 group)
117 { 112 {
118 OscarConnection *cur; 113 OscarConnection *cur;
119 114
120 for (cur = sess->connlist; cur; cur = cur->next) { 115 for (cur = sess->connlist; cur; cur = cur->next)
116 {
121 aim_conn_inside_t *ins = (aim_conn_inside_t *)cur->inside; 117 aim_conn_inside_t *ins = (aim_conn_inside_t *)cur->inside;
122 struct snacgroup *sg; 118 struct snacgroup *sg;
123 119
124 for (sg = ins->groups; sg; sg = sg->next) { 120 for (sg = ins->groups; sg; sg = sg->next)
121 {
125 if (sg->group == group) 122 if (sg->group == group)
126 return cur; 123 return cur;
127 } 124 }
128 } 125 }
129 126
130 return NULL; 127 return NULL;
131 } 128 }
132 129
133 static void connkill_snacgroups(struct snacgroup **head) 130 static void
131 connkill_snacgroups(struct snacgroup *head)
134 { 132 {
135 struct snacgroup *sg; 133 struct snacgroup *sg;
136 134
137 for (sg = *head; sg; ) { 135 for (sg = head; sg; )
136 {
138 struct snacgroup *tmp; 137 struct snacgroup *tmp;
139 138
140 tmp = sg->next; 139 tmp = sg->next;
141 free(sg); 140 free(sg);
142 sg = tmp; 141 sg = tmp;
143 } 142 }
144 143 }
145 *head = NULL; 144
146 145 static void
147 return; 146 connkill_rates(struct rateclass *head)
148 }
149
150 static void connkill_rates(struct rateclass **head)
151 { 147 {
152 struct rateclass *rc; 148 struct rateclass *rc;
153 149
154 for (rc = *head; rc; ) { 150 for (rc = head; rc; )
151 {
155 struct rateclass *tmp; 152 struct rateclass *tmp;
156 struct snacpair *sp; 153 struct snacpair *sp;
157 154
158 tmp = rc->next; 155 tmp = rc->next;
159 156
166 } 163 }
167 free(rc); 164 free(rc);
168 165
169 rc = tmp; 166 rc = tmp;
170 } 167 }
171 168 }
172 *head = NULL; 169
173 170 static void
174 return; 171 connkill_real(OscarSession *sess, OscarConnection *conn)
175 } 172 {
176 173
177 static void connkill_real(OscarSession *sess, OscarConnection **deadconn) 174 aim_rxqueue_cleanbyconn(sess, conn);
178 { 175 aim_tx_cleanqueue(sess, conn);
179 176
180 aim_rxqueue_cleanbyconn(sess, *deadconn); 177 if (conn->fd != -1)
181 aim_tx_cleanqueue(sess, *deadconn); 178 aim_conn_close(conn);
182
183 if ((*deadconn)->fd != -1)
184 aim_conn_close(*deadconn);
185 179
186 /* 180 /*
187 * This will free ->internal if it necessary... 181 * This will free ->internal if it necessary...
188 */ 182 */
189 if ((*deadconn)->type == AIM_CONN_TYPE_CHAT) 183 if (conn->type == AIM_CONN_TYPE_CHAT)
190 aim_conn_kill_chat(sess, *deadconn); 184 aim_conn_kill_chat(sess, conn);
191 185
192 if ((*deadconn)->inside) { 186 if (conn->inside)
193 aim_conn_inside_t *inside = (aim_conn_inside_t *)(*deadconn)->inside; 187 {
194 188 aim_conn_inside_t *inside = (aim_conn_inside_t *)conn->inside;
195 connkill_snacgroups(&inside->groups); 189
196 connkill_rates(&inside->rates); 190 connkill_snacgroups(inside->groups);
191 connkill_rates(inside->rates);
197 192
198 free(inside); 193 free(inside);
199 } 194 }
200 195
201 free(*deadconn); 196 gaim_circ_buffer_destroy(conn->buffer_outgoing);
202 *deadconn = NULL; 197 free(conn);
203
204 return;
205 } 198 }
206 199
207 /** 200 /**
208 * This sends an empty channel 4 SNAC. This is sent to signify 201 * This sends an empty channel 4 SNAC. This is sent to signify
209 * that we're logging off. This shouldn't really be necessary-- 202 * that we're logging off. This shouldn't really be necessary--
216 FlapFrame *fr; 209 FlapFrame *fr;
217 210
218 if (!sess || !conn) 211 if (!sess || !conn)
219 return -EINVAL; 212 return -EINVAL;
220 213
221 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x04, 0))) 214 if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x04, 0)))
222 return -ENOMEM; 215 return -ENOMEM;
223 216
224 aim_tx_enqueue(sess, fr); 217 aim_tx_enqueue(sess, fr);
225 218
226 return 0; 219 return 0;
227 } 220 }
228 221
229 /** 222 /**
230 * Clears out the connection list, killing remaining connections.
231 *
232 * @param sess Session to be cleared.
233 */
234 static void aim_connrst(OscarSession *sess)
235 {
236
237 if (sess->connlist) {
238 OscarConnection *cur = sess->connlist, *tmp;
239
240 /* Attempt to send the log-off packet */
241 if (cur->type == AIM_CONN_TYPE_BOS)
242 aim_flap_close(sess, cur);
243
244 while (cur) {
245 tmp = cur->next;
246 aim_conn_close(cur);
247 connkill_real(sess, &cur);
248 cur = tmp;
249 }
250 }
251
252 sess->connlist = NULL;
253
254 return;
255 }
256
257 /**
258 * Initializes and/or resets a connection structure to the default values.
259 *
260 * @param deadconn Connection to be reset.
261 */
262 static void aim_conn_init(OscarConnection *deadconn)
263 {
264
265 if (!deadconn)
266 return;
267
268 deadconn->fd = -1;
269 deadconn->subtype = -1;
270 deadconn->type = -1;
271 deadconn->seqnum = 0;
272 deadconn->lastactivity = 0;
273 deadconn->forcedlatency = 0;
274 deadconn->handlerlist = NULL;
275 deadconn->priv = NULL;
276 memset(deadconn->inside, 0, sizeof(aim_conn_inside_t));
277
278 return;
279 }
280
281 /**
282 * Allocate a new empty connection structure. 223 * Allocate a new empty connection structure.
283 * 224 *
284 * @param sess Session 225 * @param sess The oscar session associated with this connection.
285 * @return Returns the new connection structure. 226 * @return Returns the new connection structure.
286 */ 227 */
287 static OscarConnection *aim_conn_getnext(OscarSession *sess) 228 static OscarConnection *
288 { 229 aim_conn_getnext(OscarSession *sess)
289 OscarConnection *newconn; 230 {
290 231 OscarConnection *conn;
291 if (!(newconn = malloc(sizeof(OscarConnection)))) 232
292 return NULL; 233 conn = g_new0(OscarConnection, 1);
293 memset(newconn, 0, sizeof(OscarConnection)); 234 conn->inside = g_new0(aim_conn_inside_t, 1);
294 235 conn->buffer_outgoing = gaim_circ_buffer_new(-1);
295 if (!(newconn->inside = malloc(sizeof(aim_conn_inside_t)))) { 236 conn->fd = -1;
296 free(newconn); 237 conn->subtype = -1;
297 return NULL; 238 conn->type = -1;
298 } 239 conn->seqnum = 0;
299 memset(newconn->inside, 0, sizeof(aim_conn_inside_t)); 240 conn->lastactivity = 0;
300 241 conn->forcedlatency = 0;
301 aim_conn_init(newconn); 242 conn->handlerlist = NULL;
302 243
303 newconn->next = sess->connlist; 244 conn->next = sess->connlist;
304 sess->connlist = newconn; 245 sess->connlist = conn;
305 246
306 return newconn; 247 return conn;
307 } 248 }
308 249
309 /** 250 /**
310 * Close, clear, and free a connection structure. Should never be 251 * Close, clear, and free a connection structure. Should never be
311 * called from within libfaim. 252 * called from within libfaim.
312 * 253 *
313 * @param sess Session for the connection. 254 * @param sess Session for the connection.
314 * @param deadconn Connection to be freed. 255 * @param deadconn Connection to be freed.
315 */ 256 */
316 faim_export void aim_conn_kill(OscarSession *sess, OscarConnection **deadconn) 257 void
258 aim_conn_kill(OscarSession *sess, OscarConnection **deadconn)
317 { 259 {
318 OscarConnection *cur, **prev; 260 OscarConnection *cur, **prev;
319 261
320 if (!deadconn || !*deadconn) 262 if (!deadconn || !*deadconn)
321 return; 263 return;
329 } 271 }
330 272
331 if (!cur) 273 if (!cur)
332 return; /* oops */ 274 return; /* oops */
333 275
334 connkill_real(sess, &cur); 276 connkill_real(sess, cur);
335
336 return;
337 } 277 }
338 278
339 /** 279 /**
340 * Close (but not free) a connection. 280 * Close (but not free) a connection.
341 * 281 *
342 * This leaves everything untouched except for clearing the 282 * This leaves everything untouched except for clearing the
343 * handler list and setting the fd to -1 (used to recognize 283 * handler list and setting the fd to -1 (used to recognize
344 * dead connections). It will also remove cookies if necessary. 284 * dead connections). It will also remove cookies if necessary.
345 * 285 *
346 * Why only if fd >= 3? Seems rather implementation specific... 286 * Why only if fd >= 3? Seems rather implementation specific...
347 * fd's do not have to be distributed in a particular order, do they? 287 * fd's do not have to be distributed in a particular order, do they?
348 * 288 *
349 * @param deadconn The connection to close. 289 * @param deadconn The connection to close.
350 */ 290 */
351 faim_export void aim_conn_close(OscarConnection *deadconn) 291 void
292 aim_conn_close(OscarConnection *deadconn)
352 { 293 {
353 aim_rxcallback_t userfunc; 294 aim_rxcallback_t userfunc;
354 295
355 if (deadconn->fd >= 0) 296 if (deadconn->fd >= 0)
356 close(deadconn->fd); 297 close(deadconn->fd);
360 if ((userfunc = aim_callhandler(deadconn->sessv, deadconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNDEAD))) 301 if ((userfunc = aim_callhandler(deadconn->sessv, deadconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNDEAD)))
361 userfunc(deadconn->sessv, NULL, deadconn); 302 userfunc(deadconn->sessv, NULL, deadconn);
362 303
363 if (deadconn->handlerlist) 304 if (deadconn->handlerlist)
364 aim_clearhandlers(deadconn); 305 aim_clearhandlers(deadconn);
365 306 }
366 return; 307
367 } 308 /**
368 309 * Locates a connection of the specified type in the
369 /**
370 * Locates a connection of the specified type in the
371 * specified session. 310 * specified session.
372 * 311 *
373 * XXX - Except for rendezvous, all uses of this should be removed and 312 * XXX - Except for rendezvous, all uses of this should be removed and
374 * aim_conn_findbygroup() should be used instead. 313 * aim_conn_findbygroup() should be used instead.
375 * 314 *
376 * @param sess The session to search. 315 * @param sess The session to search.
377 * @param type The type of connection to look for. 316 * @param type The type of connection to look for.
378 * @return Returns the first connection found of the given target type, 317 * @return Returns the first connection found of the given target type,
379 * or NULL if none could be found. 318 * or NULL if none could be found.
380 */ 319 */
381 faim_export OscarConnection *aim_getconn_type(OscarSession *sess, int type) 320 OscarConnection *
321 aim_getconn_type(OscarSession *sess, int type)
382 { 322 {
383 OscarConnection *cur; 323 OscarConnection *cur;
384 324
385 for (cur = sess->connlist; cur; cur = cur->next) { 325 for (cur = sess->connlist; cur; cur = cur->next) {
386 if ((cur->type == type) && 326 if ((cur->type == type) &&
389 } 329 }
390 330
391 return cur; 331 return cur;
392 } 332 }
393 333
394 faim_export OscarConnection *aim_getconn_type_all(OscarSession *sess, int type) 334 OscarConnection *
335 aim_getconn_type_all(OscarSession *sess, int type)
395 { 336 {
396 OscarConnection *cur; 337 OscarConnection *cur;
397 338
398 for (cur = sess->connlist; cur; cur = cur->next) { 339 for (cur = sess->connlist; cur; cur = cur->next) {
399 if (cur->type == type) 340 if (cur->type == type)
402 343
403 return cur; 344 return cur;
404 } 345 }
405 346
406 /* If you pass -1 for the fd, you'll get what you ask for. Gibberish. */ 347 /* If you pass -1 for the fd, you'll get what you ask for. Gibberish. */
407 faim_export OscarConnection *aim_getconn_fd(OscarSession *sess, int fd) 348 OscarConnection *
349 aim_getconn_fd(OscarSession *sess, int fd)
408 { 350 {
409 OscarConnection *cur; 351 OscarConnection *cur;
410 352
411 for (cur = sess->connlist; cur; cur = cur->next) { 353 for (cur = sess->connlist; cur; cur = cur->next) {
412 if (cur->fd == fd) 354 if (cur->fd == fd)
418 360
419 /** 361 /**
420 * Clone an OscarConnection. 362 * Clone an OscarConnection.
421 * 363 *
422 * A new connection is allocated, and the values are filled in 364 * A new connection is allocated, and the values are filled in
423 * appropriately. Note that this function sets the new connnection's 365 * appropriately.
424 * ->priv pointer to be equal to that of its parent: only the pointer
425 * is copied, not the data it points to.
426 * 366 *
427 * @param sess The session containing this connection. 367 * @param sess The session containing this connection.
428 * @param src The connection to clone. 368 * @param src The connection to clone.
429 * @return Returns a pointer to the new OscarConnection, or %NULL on error. 369 * @return Returns a pointer to the new OscarConnection, or %NULL on error.
430 */ 370 */
431 faim_internal OscarConnection *aim_cloneconn(OscarSession *sess, OscarConnection *src) 371 OscarConnection *
372 aim_cloneconn(OscarSession *sess, OscarConnection *src)
432 { 373 {
433 OscarConnection *conn; 374 OscarConnection *conn;
434 375
435 if (!(conn = aim_conn_getnext(sess))) 376 if (!(conn = aim_conn_getnext(sess)))
436 return NULL; 377 return NULL;
437 378
438 conn->fd = src->fd; 379 conn->fd = src->fd;
439 conn->type = src->type; 380 conn->type = src->type;
440 conn->subtype = src->subtype; 381 conn->subtype = src->subtype;
441 conn->seqnum = src->seqnum; 382 conn->seqnum = src->seqnum;
442 conn->priv = src->priv;
443 conn->internal = src->internal; 383 conn->internal = src->internal;
444 conn->lastactivity = src->lastactivity; 384 conn->lastactivity = src->lastactivity;
445 conn->forcedlatency = src->forcedlatency; 385 conn->forcedlatency = src->forcedlatency;
446 conn->sessv = src->sessv; 386 conn->sessv = src->sessv;
447 aim_clonehandlers(sess, conn, src); 387 aim_clonehandlers(sess, conn, src);
449 if (src->inside) { 389 if (src->inside) {
450 /* 390 /*
451 * XXX should clone this section as well, but since currently 391 * XXX should clone this section as well, but since currently
452 * this function only gets called for some of that rendezvous 392 * this function only gets called for some of that rendezvous
453 * crap, and not on SNAC connections, its probably okay for 393 * crap, and not on SNAC connections, its probably okay for
454 * now. 394 * now.
455 * 395 *
456 */ 396 */
457 } 397 }
458 398
459 return conn; 399 return conn;
468 * FIXME: Return errors in a more sane way. 408 * FIXME: Return errors in a more sane way.
469 * 409 *
470 * @param sess Session to create connection in 410 * @param sess Session to create connection in
471 * @param type Type of connection to create 411 * @param type Type of connection to create
472 */ 412 */
473 faim_export OscarConnection *aim_newconn(OscarSession *sess, int type) 413 OscarConnection *
414 aim_newconn(OscarSession *sess, int type)
474 { 415 {
475 OscarConnection *conn; 416 OscarConnection *conn;
476 417
477 if (!(conn = aim_conn_getnext(sess))) 418 if (!(conn = aim_conn_getnext(sess)))
478 return NULL; 419 return NULL;
516 * 457 *
517 * @param conn Conn to set latency for. 458 * @param conn Conn to set latency for.
518 * @param newval Number of seconds to force between transmits. 459 * @param newval Number of seconds to force between transmits.
519 * @return Returns -1 if the connection does not exist, zero otherwise. 460 * @return Returns -1 if the connection does not exist, zero otherwise.
520 */ 461 */
521 faim_export int aim_conn_setlatency(OscarConnection *conn, int newval) 462 int
463 aim_conn_setlatency(OscarConnection *conn, int newval)
522 { 464 {
523 465
524 if (!conn) 466 if (!conn)
525 return -1; 467 return -1;
526 468
529 471
530 return 0; 472 return 0;
531 } 473 }
532 474
533 /** 475 /**
534 * Initializes a session structure by setting the initial values 476 * Allocates a new OscarSession and initializes it with default values.
535 * stuff in the OscarSession struct. 477 */
536 * 478 OscarSession *
537 * @param sess Session to initialize. 479 oscar_session_new(void)
538 * @param nonblocking Set to true if you want connections to be non-blocking. 480 {
539 */ 481 OscarSession *sess;
540 faim_export void aim_session_init(OscarSession *sess, guint8 nonblocking) 482
541 { 483 sess = g_new(OscarSession, 1);
542 484
543 if (!sess)
544 return;
545
546 memset(sess, 0, sizeof(OscarSession));
547 aim_connrst(sess);
548 sess->queue_outgoing = NULL; 485 sess->queue_outgoing = NULL;
549 sess->queue_incoming = NULL; 486 sess->queue_incoming = NULL;
550 aim_initsnachash(sess); 487 aim_initsnachash(sess);
551 sess->msgcookies = NULL; 488 sess->msgcookies = NULL;
552 sess->nonblocking = nonblocking;
553 sess->modlistv = NULL; 489 sess->modlistv = NULL;
554 sess->snacid_next = 0x00000001; 490 sess->snacid_next = 0x00000001;
555 491
556 sess->locate.userinfo = NULL; 492 sess->locate.userinfo = NULL;
557 sess->locate.torequest = NULL; 493 sess->locate.torequest = NULL;
601 aim__registermodule(sess, icq_modfirst); /* XXX - Make sure this isn't sent for AIM */ 537 aim__registermodule(sess, icq_modfirst); /* XXX - Make sure this isn't sent for AIM */
602 /* missing 0x16 */ 538 /* missing 0x16 */
603 aim__registermodule(sess, auth_modfirst); 539 aim__registermodule(sess, auth_modfirst);
604 aim__registermodule(sess, email_modfirst); 540 aim__registermodule(sess, email_modfirst);
605 541
606 return; 542 return sess;
607 } 543 }
608 544
609 /** 545 /**
610 * Logoff and deallocate a session. 546 * Logoff and deallocate a session.
611 * 547 *
612 * @param sess Session to kill 548 * @param sess Session to kill
613 */ 549 */
614 faim_export void aim_session_kill(OscarSession *sess) 550 void
551 oscar_session_destroy(OscarSession *sess)
615 { 552 {
616 aim_cleansnacs(sess, -1); 553 aim_cleansnacs(sess, -1);
617 554
618 aim_logoff(sess); 555 if (sess->connlist) {
556 OscarConnection *cur = sess->connlist, *tmp;
557
558 /* Attempt to send the log-off packet */
559 if (cur->type == AIM_CONN_TYPE_BOS)
560 aim_flap_close(sess, cur);
561
562 while (cur) {
563 tmp = cur->next;
564 aim_conn_close(cur);
565 connkill_real(sess, cur);
566 cur = tmp;
567 }
568 }
569 sess->connlist = NULL;
619 570
620 aim__shutdownmodules(sess); 571 aim__shutdownmodules(sess);
621 572
622 return; 573 g_free(sess);
623 } 574 }
624 575
625 /** 576 /**
626 * Determine if a connection is connecting. 577 * Determine if a connection is connecting.
627 * 578 *
628 * @param conn Connection to examine. 579 * @param conn Connection to examine.
629 * @return Returns nonzero if the connection is in the process of 580 * @return Returns nonzero if the connection is in the process of
630 * connecting (or if it just completed and 581 * connecting (or if it just completed and
631 * aim_conn_completeconnect() has yet to be called on it). 582 * aim_conn_completeconnect() has yet to be called on it).
632 */ 583 */
633 faim_export int aim_conn_isconnecting(OscarConnection *conn) 584 int
585 aim_conn_isconnecting(OscarConnection *conn)
634 { 586 {
635 587
636 if (!conn) 588 if (!conn)
637 return 0; 589 return 0;
638 590
640 } 592 }
641 593
642 /* 594 /*
643 * XXX this is nearly as ugly as proxyconnect(). 595 * XXX this is nearly as ugly as proxyconnect().
644 */ 596 */
645 faim_export int aim_conn_completeconnect(OscarSession *sess, OscarConnection *conn) 597 int
598 aim_conn_completeconnect(OscarSession *sess, OscarConnection *conn)
646 { 599 {
647 aim_rxcallback_t userfunc; 600 aim_rxcallback_t userfunc;
648 601
649 if (!conn || (conn->fd == -1)) 602 if (!conn || (conn->fd == -1))
650 return -1; 603 return -1;
663 aim_tx_flushqueue(sess); 616 aim_tx_flushqueue(sess);
664 617
665 return 0; 618 return 0;
666 } 619 }
667 620
668 faim_export OscarSession *aim_conn_getsess(OscarConnection *conn) 621 OscarSession *
622 aim_conn_getsess(OscarConnection *conn)
669 { 623 {
670 624
671 if (!conn) 625 if (!conn)
672 return NULL; 626 return NULL;
673 627
674 return (OscarSession *)conn->sessv; 628 return (OscarSession *)conn->sessv;
675 } 629 }
676 630
677 /** 631 /**
678 * Close -ALL- open connections.
679 *
680 * @param sess The session.
681 * @return Zero.
682 */
683 faim_export int aim_logoff(OscarSession *sess)
684 {
685 aim_connrst(sess); /* in case we want to connect again */
686
687 return 0;
688 }
689
690 /**
691 * No-op. This sends an empty channel 5 SNAC. WinAIM 4.x and higher 632 * No-op. This sends an empty channel 5 SNAC. WinAIM 4.x and higher
692 * sends these _every minute_ to keep the connection alive. 633 * sends these _every minute_ to keep the connection alive.
693 */ 634 */
694 faim_export int aim_flap_nop(OscarSession *sess, OscarConnection *conn) 635 int
636 aim_flap_nop(OscarSession *sess, OscarConnection *conn)
695 { 637 {
696 FlapFrame *fr; 638 FlapFrame *fr;
697 639
698 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x05, 0))) 640 if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x05, 0)))
699 return -ENOMEM; 641 return -ENOMEM;
700 642
701 aim_tx_enqueue(sess, fr); 643 aim_tx_enqueue(sess, fr);
702 644
703 /* clean out SNACs over 60sec old */ 645 /* clean out SNACs over 60sec old */