src/protocols/oscar/conn.c

changeset 13254
3fbb3f3efba7
parent 13253
5ad8373f2d1e
child 13255
b318f395092d
equal deleted inserted replaced
13253:5ad8373f2d1e 13254:3fbb3f3efba7
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 */

mercurial