Mercurial > pidgin
changeset 13592:6519aeb66b31
[gaim-migrate @ 15978]
Holy cow this is crazy.
34 files changed, 5760 insertions(+), 8517 deletions(-)
* Non-blocking I/O for all of oscar. That includes normal FLAP
connections as well as file transfers and direct IM.
* Kick-ass file transfer and direct IM. Either party can request
the connection. Gaim will try both the "public" IP and the
"client" IP. It'll fall back to transferring through a proxy
if that fails. Should be relatively few memleaks (I didn't
have a lot of confidence in the non-memleakiness of the old
code). And the code is reasonably generic, so it shouldn't
be too much work to add voice chat. This might still be a
LITTLE buggy, but it shouldn't be too bad. If anything, file
transfer will be more buggy than direct IM. And sending a
file will be more buggy than receiving a file. Bug reports
with a series of steps to reproduce are welcome.
* I merged OscarData and aim_session_t
* Somewhere between 50 and 100 hours of work.
committer: Tailor Script <tailor@pidgin.im>
line wrap: on
line diff
--- a/src/protocols/oscar/Makefile.am Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/Makefile.am Fri Apr 07 05:10:56 2006 +0000 @@ -7,7 +7,6 @@ OSCARSOURCES = \ bstream.c \ - conn.c \ family_admin.c \ family_advert.c \ family_alert.c \ @@ -28,20 +27,21 @@ family_stats.c \ family_translate.c \ family_userlookup.c \ + flap_connection.c \ misc.c \ msgcookie.c \ + odc.c \ + oft.c \ oscar.c \ oscar.h \ - oscar_internal.h \ + oscar_data.c \ peer.c \ peer.h \ + peer_proxy.c \ rxhandlers.c \ - rxqueue.c \ - session.c \ snac.c \ snactypes.h \ tlv.c \ - txqueue.c \ util.c AM_CFLAGS = $(st)
--- a/src/protocols/oscar/Makefile.mingw Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/Makefile.mingw Fri Apr 07 05:10:56 2006 +0000 @@ -69,7 +69,6 @@ C_SRC = \ bstream.c \ - conn.c \ family_admin.c \ family_advert.c \ family_alert.c \ @@ -90,16 +89,18 @@ family_stats.c \ family_translate.c \ family_userlookup.c \ + flap_connection.c \ misc.c \ msgcookie.c \ + odc.c \ + oft.c \ oscar.c \ + oscar_data.c \ peer.c \ + peer_proxy.c \ rxhandlers.c \ - rxqueue.c \ - session.c \ snac.c \ tlv.c \ - txqueue.c \ util.c
--- a/src/protocols/oscar/bstream.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/bstream.c Fri Apr 07 05:10:56 2006 +0000 @@ -24,7 +24,7 @@ #include "oscar.h" -faim_internal int aim_bstream_init(ByteStream *bs, guint8 *data, int len) +int byte_stream_init(ByteStream *bs, guint8 *data, int len) { if (!bs) @@ -37,17 +37,17 @@ return 0; } -faim_internal int aim_bstream_empty(ByteStream *bs) +int byte_stream_empty(ByteStream *bs) { return bs->len - bs->offset; } -faim_internal int aim_bstream_curpos(ByteStream *bs) +int byte_stream_curpos(ByteStream *bs) { return bs->offset; } -faim_internal int aim_bstream_setpos(ByteStream *bs, unsigned int off) +int byte_stream_setpos(ByteStream *bs, unsigned int off) { if (off > bs->len) @@ -58,10 +58,10 @@ return off; } -faim_internal void aim_bstream_rewind(ByteStream *bs) +void byte_stream_rewind(ByteStream *bs) { - aim_bstream_setpos(bs, 0); + byte_stream_setpos(bs, 0); return; } @@ -71,10 +71,10 @@ * in a bstream. I'm not sure if libfaim actually does * this anywhere... */ -faim_internal int aim_bstream_advance(ByteStream *bs, int n) +int byte_stream_advance(ByteStream *bs, int n) { - if ((aim_bstream_curpos(bs) + n < 0) || (aim_bstream_empty(bs) < n)) + if ((byte_stream_curpos(bs) + n < 0) || (byte_stream_empty(bs) < n)) return 0; /* XXX throw an exception */ bs->offset += n; @@ -82,10 +82,10 @@ return n; } -faim_internal guint8 aimbs_get8(ByteStream *bs) +guint8 byte_stream_get8(ByteStream *bs) { - if (aim_bstream_empty(bs) < 1) + if (byte_stream_empty(bs) < 1) return 0; /* XXX throw an exception */ bs->offset++; @@ -93,10 +93,10 @@ return aimutil_get8(bs->data + bs->offset - 1); } -faim_internal guint16 aimbs_get16(ByteStream *bs) +guint16 byte_stream_get16(ByteStream *bs) { - if (aim_bstream_empty(bs) < 2) + if (byte_stream_empty(bs) < 2) return 0; /* XXX throw an exception */ bs->offset += 2; @@ -104,10 +104,10 @@ return aimutil_get16(bs->data + bs->offset - 2); } -faim_internal guint32 aimbs_get32(ByteStream *bs) +guint32 byte_stream_get32(ByteStream *bs) { - if (aim_bstream_empty(bs) < 4) + if (byte_stream_empty(bs) < 4) return 0; /* XXX throw an exception */ bs->offset += 4; @@ -115,10 +115,10 @@ return aimutil_get32(bs->data + bs->offset - 4); } -faim_internal guint8 aimbs_getle8(ByteStream *bs) +guint8 byte_stream_getle8(ByteStream *bs) { - if (aim_bstream_empty(bs) < 1) + if (byte_stream_empty(bs) < 1) return 0; /* XXX throw an exception */ bs->offset++; @@ -126,10 +126,10 @@ return aimutil_getle8(bs->data + bs->offset - 1); } -faim_internal guint16 aimbs_getle16(ByteStream *bs) +guint16 byte_stream_getle16(ByteStream *bs) { - if (aim_bstream_empty(bs) < 2) + if (byte_stream_empty(bs) < 2) return 0; /* XXX throw an exception */ bs->offset += 2; @@ -137,10 +137,10 @@ return aimutil_getle16(bs->data + bs->offset - 2); } -faim_internal guint32 aimbs_getle32(ByteStream *bs) +guint32 byte_stream_getle32(ByteStream *bs) { - if (aim_bstream_empty(bs) < 4) + if (byte_stream_empty(bs) < 4) return 0; /* XXX throw an exception */ bs->offset += 4; @@ -148,10 +148,10 @@ return aimutil_getle32(bs->data + bs->offset - 4); } -faim_internal int aimbs_getrawbuf(ByteStream *bs, guint8 *buf, int len) +int byte_stream_getrawbuf(ByteStream *bs, guint8 *buf, int len) { - if (aim_bstream_empty(bs) < len) + if (byte_stream_empty(bs) < len) return 0; memcpy(buf, bs->data + bs->offset, len); @@ -160,14 +160,13 @@ return len; } -faim_internal guint8 *aimbs_getraw(ByteStream *bs, int len) +guint8 *byte_stream_getraw(ByteStream *bs, int len) { guint8 *ob; - if (!(ob = malloc(len))) - return NULL; + ob = malloc(len); - if (aimbs_getrawbuf(bs, ob, len) < len) { + if (byte_stream_getrawbuf(bs, ob, len) < len) { free(ob); return NULL; } @@ -175,14 +174,13 @@ return ob; } -faim_internal char *aimbs_getstr(ByteStream *bs, int len) +char *byte_stream_getstr(ByteStream *bs, int len) { char *ob; - if (!(ob = malloc(len + 1))) - return NULL; + ob = malloc(len + 1); - if (aimbs_getrawbuf(bs, (guint8 *)ob, len) < len) { + if (byte_stream_getrawbuf(bs, (guint8 *)ob, len) < len) { free(ob); return NULL; } @@ -192,10 +190,10 @@ return ob; } -faim_internal int aimbs_put8(ByteStream *bs, guint8 v) +int byte_stream_put8(ByteStream *bs, guint8 v) { - if (aim_bstream_empty(bs) < 1) + if (byte_stream_empty(bs) < 1) return 0; /* XXX throw an exception */ bs->offset += aimutil_put8(bs->data + bs->offset, v); @@ -203,10 +201,10 @@ return 1; } -faim_internal int aimbs_put16(ByteStream *bs, guint16 v) +int byte_stream_put16(ByteStream *bs, guint16 v) { - if (aim_bstream_empty(bs) < 2) + if (byte_stream_empty(bs) < 2) return 0; /* XXX throw an exception */ bs->offset += aimutil_put16(bs->data + bs->offset, v); @@ -214,10 +212,10 @@ return 2; } -faim_internal int aimbs_put32(ByteStream *bs, guint32 v) +int byte_stream_put32(ByteStream *bs, guint32 v) { - if (aim_bstream_empty(bs) < 4) + if (byte_stream_empty(bs) < 4) return 0; /* XXX throw an exception */ bs->offset += aimutil_put32(bs->data + bs->offset, v); @@ -225,10 +223,10 @@ return 1; } -faim_internal int aimbs_putle8(ByteStream *bs, guint8 v) +int byte_stream_putle8(ByteStream *bs, guint8 v) { - if (aim_bstream_empty(bs) < 1) + if (byte_stream_empty(bs) < 1) return 0; /* XXX throw an exception */ bs->offset += aimutil_putle8(bs->data + bs->offset, v); @@ -236,10 +234,10 @@ return 1; } -faim_internal int aimbs_putle16(ByteStream *bs, guint16 v) +int byte_stream_putle16(ByteStream *bs, guint16 v) { - if (aim_bstream_empty(bs) < 2) + if (byte_stream_empty(bs) < 2) return 0; /* XXX throw an exception */ bs->offset += aimutil_putle16(bs->data + bs->offset, v); @@ -247,10 +245,10 @@ return 2; } -faim_internal int aimbs_putle32(ByteStream *bs, guint32 v) +int byte_stream_putle32(ByteStream *bs, guint32 v) { - if (aim_bstream_empty(bs) < 4) + if (byte_stream_empty(bs) < 4) return 0; /* XXX throw an exception */ bs->offset += aimutil_putle32(bs->data + bs->offset, v); @@ -259,10 +257,10 @@ } -faim_internal int aimbs_putraw(ByteStream *bs, const guint8 *v, int len) +int byte_stream_putraw(ByteStream *bs, const guint8 *v, int len) { - if (aim_bstream_empty(bs) < len) + if (byte_stream_empty(bs) < len) return 0; /* XXX throw an exception */ memcpy(bs->data + bs->offset, v, len); @@ -271,18 +269,18 @@ return len; } -faim_internal int aimbs_putstr(ByteStream *bs, const char *str) +int byte_stream_putstr(ByteStream *bs, const char *str) { - return aimbs_putraw(bs, (guint8 *)str, strlen(str)); + return byte_stream_putraw(bs, (guint8 *)str, strlen(str)); } -faim_internal int aimbs_putbs(ByteStream *bs, ByteStream *srcbs, int len) +int byte_stream_putbs(ByteStream *bs, ByteStream *srcbs, int len) { - if (aim_bstream_empty(srcbs) < len) + if (byte_stream_empty(srcbs) < len) return 0; /* XXX throw exception (underrun) */ - if (aim_bstream_empty(bs) < len) + if (byte_stream_empty(bs) < len) return 0; /* XXX throw exception (overflow) */ memcpy(bs->data + bs->offset, srcbs->data + srcbs->offset, len);
--- a/src/protocols/oscar/conn.c Fri Apr 07 01:05:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,452 +0,0 @@ -/* - * 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 -*/ - -/** - * Low-level connection handling. - * - * Does all this gloriously nifty connection handling stuff... - * - */ - -#include "oscar.h" - -#ifndef _WIN32 -#include <netdb.h> -#include <sys/socket.h> -#include <netinet/in.h> -#endif - -#ifdef _WIN32 -#include "win32dep.h" -#endif - -/** - * In OSCAR, every connection has a set of SNAC groups associated - * with it. These are the groups that you can send over this connection - * without being guaranteed a "Not supported" SNAC error. - * - * The grand theory of things says that these associations transcend - * what libfaim calls "connection types" (conn->type). You can probably - * see the elegance here, but since I want to revel in it for a bit, you - * get to hear it all spelled out. - * - * So let us say that you have your core BOS connection running. One - * of your modules has just given you a SNAC of the group 0x0004 to send - * you. Maybe an IM destined for some twit in Greenland. So you start - * at the top of your connection list, looking for a connection that - * claims to support group 0x0004. You find one. Why, that neat BOS - * connection of yours can do that. So you send it on its way. - * - * Now, say, that fellow from Greenland has friends and they all want to - * meet up with you in a lame chat room. This has landed you a SNAC - * in the family 0x000e and you have to admit you're a bit lost. You've - * searched your connection list for someone who wants to make your life - * easy and deliver this SNAC for you, but there isn't one there. - * - * Here comes the good bit. Without even letting anyone know, particularly - * the module that decided to send this SNAC, and definitely not that twit - * in Greenland, you send out a service request. In this request, you have - * marked the need for a connection supporting group 0x000e. A few seconds - * later, you receive a service redirect with an IP address and a cookie in - * it. Great, you say. Now I have something to do. Off you go, making - * that connection. One of the first things you get from this new server - * is a message saying that indeed it does support the group you were looking - * for. So you continue and send rate confirmation and all that. - * - * Then you remember you had that SNAC to send, and now you have a means to - * do it, and you do, and everyone is happy. Except the Greenlander, who is - * still stuck in the bitter cold. - * - * Oh, and this is useful for building the Migration SNACs, too. In the - * future, this may help convince me to implement rate limit mitigation - * for real. We'll see. - * - * Just to make me look better, I'll say that I've known about this great - * scheme for quite some time now. But I still haven't convinced myself - * to make libfaim work that way. It would take a fair amount of effort, - * and probably some client API changes as well. (Whenever I don't want - * to do something, I just say it would change the client API. Then I - * instantly have a couple of supporters of not doing it.) - * - * Generally, addgroup is only called by the internal handling of the - * server ready SNAC. So if you want to do something before that, you'll - * have to be more creative. That is done rather early, though, so I don't - * think you have to worry about it. Unless you're me. I care deeply - * about such inane things. - * - */ -void -aim_conn_addgroup(OscarConnection *conn, guint16 group) -{ - aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; - struct snacgroup *sg; - - sg = g_new0(struct snacgroup, 1); - - gaim_debug_misc("oscar", "adding group 0x%04x\n", group); - sg->group = group; - - sg->next = ins->groups; - ins->groups = sg; -} - -OscarConnection * -aim_conn_findbygroup(OscarSession *sess, guint16 group) -{ - GList *cur;; - - for (cur = sess->oscar_connections; cur; cur = cur->next) - { - OscarConnection *conn; - aim_conn_inside_t *ins; - struct snacgroup *sg; - - conn = cur->data; - ins = (aim_conn_inside_t *)conn->inside; - - for (sg = ins->groups; sg; sg = sg->next) - { - if (sg->group == group) - return conn; - } - } - - return NULL; -} - -static void -connkill_snacgroups(struct snacgroup *head) -{ - struct snacgroup *sg; - for (sg = head; sg; ) - { - struct snacgroup *tmp; - - tmp = sg->next; - free(sg); - sg = tmp; - } -} - -static void -connkill_rates(struct rateclass *head) -{ - struct rateclass *rc; - - for (rc = head; rc; ) - { - struct rateclass *tmp; - struct snacpair *sp; - - tmp = rc->next; - - for (sp = rc->members; sp; ) { - struct snacpair *tmpsp; - - tmpsp = sp->next; - free(sp); - sp = tmpsp; - } - free(rc); - - rc = tmp; - } -} - -void -oscar_connection_destroy(OscarSession *sess, OscarConnection *conn) -{ - aim_rxqueue_cleanbyconn(sess, conn); - aim_tx_cleanqueue(sess, conn); - - if (conn->fd != -1) - aim_conn_close(sess, conn); - - /* - * This will free ->internal if it necessary... - */ - if (conn->type == AIM_CONN_TYPE_CHAT) - oscar_connection_destroy_chat(sess, conn); - - if (conn->inside != NULL) - { - aim_conn_inside_t *inside = (aim_conn_inside_t *)conn->inside; - - connkill_snacgroups(inside->groups); - connkill_rates(inside->rates); - - free(inside); - } - - gaim_circ_buffer_destroy(conn->buffer_outgoing); - g_free(conn); - - sess->oscar_connections = g_list_remove(sess->oscar_connections, conn); -} - -/** - * This sends an empty channel 4 SNAC. This is sent to signify - * that we're logging off. This shouldn't really be necessary-- - * usually the AIM server will detect that the TCP connection has - * been destroyed. - */ -static int -aim_flap_close(OscarSession *sess, OscarConnection *conn) -{ - FlapFrame *fr; - - if (!sess || !conn) - return -EINVAL; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x04, 0))) - return -ENOMEM; - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/** - * Allocate a new empty connection structure. - * - * @param sess The oscar session associated with this connection. - * @return Returns the new connection structure. - */ -static OscarConnection * -aim_conn_getnext(OscarSession *sess) -{ - OscarConnection *conn; - - conn = g_new0(OscarConnection, 1); - conn->inside = g_new0(aim_conn_inside_t, 1); - conn->buffer_outgoing = gaim_circ_buffer_new(-1); - conn->fd = -1; - conn->subtype = -1; - conn->type = -1; - conn->seqnum = 0; - conn->lastactivity = 0; - conn->handlerlist = NULL; - - sess->oscar_connections = g_list_prepend(sess->oscar_connections, conn); - - return conn; -} - -/** - * Close (but not free) a connection. - * - * This leaves everything untouched except for clearing the - * handler list and setting the fd to -1 (used to recognize - * dead connections). It will also remove cookies if necessary. - * - * @param conn The connection to close. - */ -void -aim_conn_close(OscarSession *sess, OscarConnection *conn) -{ - if (conn->type == AIM_CONN_TYPE_BOS) - aim_flap_close(sess, conn); - - if (conn->fd >= 0) - close(conn->fd); - - conn->fd = -1; - - if (conn->handlerlist) - aim_clearhandlers(conn); -} - -/** - * Locates a connection of the specified type in the - * specified session. - * - * XXX - Except for rendezvous, all uses of this should be removed and - * aim_conn_findbygroup() should be used instead. - * - * @param sess The session to search. - * @param type The type of connection to look for. - * @return Returns the first connection found of the given target type, - * or NULL if none could be found. - */ -OscarConnection * -aim_getconn_type(OscarSession *sess, int type) -{ - GList *cur; - - for (cur = sess->oscar_connections; cur; cur = cur->next) - { - OscarConnection *conn; - conn = cur->data; - if ((conn->type == type) && - !(conn->status & AIM_CONN_STATUS_INPROGRESS)) - return conn; - } - - return NULL; -} - -OscarConnection * -aim_getconn_type_all(OscarSession *sess, int type) -{ - GList *cur; - - for (cur = sess->oscar_connections; cur; cur = cur->next) - { - OscarConnection *conn; - conn = cur->data; - if (conn->type == type) - return conn; - } - - return NULL; -} - -/** - * Clone an OscarConnection. - * - * A new connection is allocated, and the values are filled in - * appropriately. - * - * @param sess The session containing this connection. - * @param src The connection to clone. - * @return Returns a pointer to the new OscarConnection, or %NULL on error. - */ -OscarConnection * -aim_cloneconn(OscarSession *sess, OscarConnection *src) -{ - OscarConnection *conn; - - conn = aim_conn_getnext(sess); - conn->fd = src->fd; - conn->type = src->type; - conn->subtype = src->subtype; - conn->seqnum = src->seqnum; - conn->internal = src->internal; - conn->lastactivity = src->lastactivity; - conn->sessv = src->sessv; - aim_clonehandlers(sess, conn, src); - - if (src->inside) { - /* - * XXX should clone this section as well, but since currently - * this function only gets called for some of that rendezvous - * crap, and not on SNAC connections, its probably okay for - * now. - * - */ - } - - return conn; -} - -/** - * Opens a new connection to the specified dest host of specified - * type, using the proxy settings if available. If @host is %NULL, - * the connection is allocated and returned, but no connection - * is made. - * - * FIXME: Return errors in a more sane way. - * - * @param sess Session to create connection in - * @param type Type of connection to create - */ -OscarConnection * -oscar_connection_new(OscarSession *sess, int type) -{ - OscarConnection *conn; - - conn = aim_conn_getnext(sess); - conn->sessv = sess; - conn->type = type; - conn->fd = -1; - conn->status = 0; - - return conn; -} - -/** - * Determine if a connection is connecting. - * - * @param conn Connection to examine. - * @return Returns nonzero if the connection is in the process of - * connecting (or if it just completed and - * aim_conn_completeconnect() has yet to be called on it). - */ -int -aim_conn_isconnecting(OscarConnection *conn) -{ - - if (!conn) - return 0; - - return !!(conn->status & AIM_CONN_STATUS_INPROGRESS); -} - -/* - * XXX this is nearly as ugly as proxyconnect(). - */ -int -aim_conn_completeconnect(OscarSession *sess, OscarConnection *conn) -{ - if (!conn || (conn->fd == -1)) - return -1; - - if (!(conn->status & AIM_CONN_STATUS_INPROGRESS)) - return -1; - - fcntl(conn->fd, F_SETFL, 0); - - conn->status &= ~AIM_CONN_STATUS_INPROGRESS; - - /* Flush out the queues if there was something waiting for this conn */ - aim_tx_flushqueue(sess); - - return 0; -} - -OscarSession * -aim_conn_getsess(OscarConnection *conn) -{ - - if (!conn) - return NULL; - - return (OscarSession *)conn->sessv; -} - -/** - * No-op. This sends an empty channel 5 SNAC. WinAIM 4.x and higher - * sends these _every minute_ to keep the connection alive. - */ -int -aim_flap_nop(OscarSession *sess, OscarConnection *conn) -{ - FlapFrame *fr; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x05, 0))) - return -ENOMEM; - - aim_tx_enqueue(sess, fr); - - /* clean out SNACs over 60sec old */ - aim_cleansnacs(sess, 60); - - return 0; -}
--- a/src/protocols/oscar/family_admin.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_admin.c Fri Apr 07 05:10:56 2006 +0000 @@ -37,21 +37,21 @@ * 0x0013 - Unknown * */ -faim_export int aim_admin_getinfo(OscarSession *sess, OscarConnection *conn, guint16 info) +int +aim_admin_getinfo(OscarData *od, FlapConnection *conn, guint16 info) { FlapFrame *fr; aim_snacid_t snacid; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 14))) - return -ENOMEM; + fr = flap_frame_new(od, 0x02, 14); - snacid = aim_cachesnac(sess, 0x0007, 0x0002, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0007, 0x0002, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0007, 0x0002, 0x0000, snacid); - aimbs_put16(&fr->data, info); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&fr->data, info); + byte_stream_put16(&fr->data, 0x0000); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, fr); return 0; } @@ -63,48 +63,48 @@ * an information change (subtype 0x0004). * */ -static int infochange(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +infochange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_rxcallback_t userfunc; char *url=NULL, *sn=NULL, *email=NULL; guint16 perms, tlvcount, err=0; - perms = aimbs_get16(bs); - tlvcount = aimbs_get16(bs); + perms = byte_stream_get16(bs); + tlvcount = byte_stream_get16(bs); - while (tlvcount && aim_bstream_empty(bs)) { + while (tlvcount && byte_stream_empty(bs)) { guint16 type, length; - type = aimbs_get16(bs); - length = aimbs_get16(bs); + type = byte_stream_get16(bs); + length = byte_stream_get16(bs); switch (type) { case 0x0001: { - sn = aimbs_getstr(bs, length); + sn = byte_stream_getstr(bs, length); } break; case 0x0004: { - url = aimbs_getstr(bs, length); + url = byte_stream_getstr(bs, length); } break; case 0x0008: { - err = aimbs_get16(bs); + err = byte_stream_get16(bs); } break; case 0x0011: { - if (length == 0) { - email = (char*)malloc(13*sizeof(char)); - strcpy(email, "*suppressed*"); - } else - email = aimbs_getstr(bs, length); + if (length == 0) + email = g_strdup("*suppressed"); + else + email = byte_stream_getstr(bs, length); } break; } tlvcount--; } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - userfunc(sess, rx, (snac->subtype == 0x0005) ? 1 : 0, perms, err, url, sn, email); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + userfunc(od, conn, frame, (snac->subtype == 0x0005) ? 1 : 0, perms, err, url, sn, email); free(sn); free(url); @@ -117,16 +117,17 @@ * Subtype 0x0004 - Set screenname formatting. * */ -faim_export int aim_admin_setnick(OscarSession *sess, OscarConnection *conn, const char *newnick) +int +aim_admin_setnick(OscarData *od, FlapConnection *conn, const char *newnick) { FlapFrame *fr; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newnick)))) + fr = flap_frame_new(od, 0x02, 10+2+2+strlen(newnick)); return -ENOMEM; - snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid); aim_tlvlist_add_str(&tl, 0x0001, newnick); @@ -134,7 +135,7 @@ aim_tlvlist_write(&fr->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, fr); return 0; @@ -144,16 +145,16 @@ * Subtype 0x0004 - Change password. * */ -faim_export int aim_admin_changepasswd(OscarSession *sess, OscarConnection *conn, const char *newpw, const char *curpw) +int +aim_admin_changepasswd(OscarData *od, FlapConnection *conn, const char *newpw, const char *curpw) { FlapFrame *fr; aim_tlvlist_t *tl = NULL; aim_snacid_t snacid; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+strlen(curpw)+4+strlen(newpw)))) - return -ENOMEM; + fr = flap_frame_new(od, 0x02, 10+4+strlen(curpw)+4+strlen(newpw)); - snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid); /* new password TLV t(0002) */ @@ -165,7 +166,7 @@ aim_tlvlist_write(&fr->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, fr); return 0; } @@ -174,16 +175,16 @@ * Subtype 0x0004 - Change email address. * */ -faim_export int aim_admin_setemail(OscarSession *sess, OscarConnection *conn, const char *newemail) +int +aim_admin_setemail(OscarData *od, FlapConnection *conn, const char *newemail) { FlapFrame *fr; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newemail)))) - return -ENOMEM; + flap_frame_new(od, 0x02, 10+2+2+strlen(newemail)); - snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid); aim_tlvlist_add_str(&tl, 0x0011, newemail); @@ -191,7 +192,7 @@ aim_tlvlist_write(&fr->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, fr); return 0; } @@ -204,47 +205,48 @@ * get the TRIAL flag removed from your account. * */ -faim_export int aim_admin_reqconfirm(OscarSession *sess, OscarConnection *conn) +int +aim_admin_reqconfirm(OscarData *od, FlapConnection *conn) { - return aim_genericreq_n(sess, conn, 0x0007, 0x0006); + return aim_genericreq_n(od, conn, 0x0007, 0x0006); } /* * Subtype 0x0007 - Account confirmation request acknowledgement. * */ -static int accountconfirm(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +accountconfirm(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; guint16 status; aim_tlvlist_t *tl; - status = aimbs_get16(bs); + status = byte_stream_get16(bs); /* This is 0x0013 if unable to confirm at this time */ tl = aim_tlvlist_read(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, status); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, status); return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005)) - return infochange(sess, mod, rx, snac, bs); + return infochange(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0007) - return accountconfirm(sess, mod, rx, snac, bs); + return accountconfirm(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int admin_modfirst(OscarSession *sess, aim_module_t *mod) +int admin_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0007; mod->version = 0x0001; mod->toolid = 0x0010;
--- a/src/protocols/oscar/family_advert.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_advert.c Fri Apr 07 05:10:56 2006 +0000 @@ -25,17 +25,17 @@ #include "oscar.h" -faim_export int aim_ads_requestads(OscarSession *sess, OscarConnection *conn) +int aim_ads_requestads(OscarData *od, FlapConnection *conn) { - return aim_genericreq_n(sess, conn, 0x0005, 0x0002); + return aim_genericreq_n(od, conn, 0x0005, 0x0002); } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) { return 0; } -faim_internal int adverts_modfirst(OscarSession *sess, aim_module_t *mod) +int adverts_modfirst(OscarData *od, aim_module_t *mod) { mod->family = 0x0005;
--- a/src/protocols/oscar/family_alert.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_alert.c Fri Apr 07 05:10:56 2006 +0000 @@ -33,48 +33,48 @@ /** * Subtype 0x0006 - Request information about your email account * - * @param sess The oscar session. + * @param od The oscar session. * @param conn The email connection for this session. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_email_sendcookies(OscarSession *sess) +int +aim_email_sendcookies(OscarData *od) { - OscarConnection *conn; + FlapConnection *conn; FlapFrame *fr; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_ALERT))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ALERT))) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+16+16))) - return -ENOMEM; - snacid = aim_cachesnac(sess, 0x0018, 0x0006, 0x0000, NULL, 0); + fr = flap_frame_new(od, 0x02, 10+2+16+16); + snacid = aim_cachesnac(od, 0x0018, 0x0006, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0018, 0x0006, 0x0000, snacid); /* Number of cookies to follow */ - aimbs_put16(&fr->data, 0x0002); + byte_stream_put16(&fr->data, 0x0002); /* Cookie */ - aimbs_put16(&fr->data, 0x5d5e); - aimbs_put16(&fr->data, 0x1708); - aimbs_put16(&fr->data, 0x55aa); - aimbs_put16(&fr->data, 0x11d3); - aimbs_put16(&fr->data, 0xb143); - aimbs_put16(&fr->data, 0x0060); - aimbs_put16(&fr->data, 0xb0fb); - aimbs_put16(&fr->data, 0x1ecb); + byte_stream_put16(&fr->data, 0x5d5e); + byte_stream_put16(&fr->data, 0x1708); + byte_stream_put16(&fr->data, 0x55aa); + byte_stream_put16(&fr->data, 0x11d3); + byte_stream_put16(&fr->data, 0xb143); + byte_stream_put16(&fr->data, 0x0060); + byte_stream_put16(&fr->data, 0xb0fb); + byte_stream_put16(&fr->data, 0x1ecb); /* Cookie */ - aimbs_put16(&fr->data, 0xb380); - aimbs_put16(&fr->data, 0x9ad8); - aimbs_put16(&fr->data, 0x0dba); - aimbs_put16(&fr->data, 0x11d5); - aimbs_put16(&fr->data, 0x9f8a); - aimbs_put16(&fr->data, 0x0060); - aimbs_put16(&fr->data, 0xb0ee); - aimbs_put16(&fr->data, 0x0631); + byte_stream_put16(&fr->data, 0xb380); + byte_stream_put16(&fr->data, 0x9ad8); + byte_stream_put16(&fr->data, 0x0dba); + byte_stream_put16(&fr->data, 0x11d5); + byte_stream_put16(&fr->data, 0x9f8a); + byte_stream_put16(&fr->data, 0x0060); + byte_stream_put16(&fr->data, 0xb0ee); + byte_stream_put16(&fr->data, 0x0631); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, fr); return 0; } @@ -92,7 +92,8 @@ * this is just a periodic status update, this will also contain * the number of unread emails that you have. */ -static int parseinfo(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +parseinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -103,11 +104,11 @@ char *alertitle = NULL, *alerturl = NULL; - cookie8 = aimbs_getraw(bs, 8); /* Possibly the code used to log you in to mail? */ - cookie16 = aimbs_getraw(bs, 16); /* Mail cookie sent above */ + cookie8 = byte_stream_getraw(bs, 8); /* Possibly the code used to log you in to mail? */ + cookie16 = byte_stream_getraw(bs, 16); /* Mail cookie sent above */ /* See if we already have some info associated with this cookie */ - for (new = sess->emailinfo; (new && memcmp(cookie16, new->cookie16, 16)); new = new->next); + for (new = od->emailinfo; (new && memcmp(cookie16, new->cookie16, 16)); new = new->next); if (new) { /* Free some of the old info, if it exists */ free(new->cookie8); @@ -116,17 +117,15 @@ free(new->domain); } else { /* We don't already have info, so create a new struct for it */ - if (!(new = malloc(sizeof(struct aim_emailinfo)))) - return -ENOMEM; - memset(new, 0, sizeof(struct aim_emailinfo)); - new->next = sess->emailinfo; - sess->emailinfo = new; + new = g_new0(struct aim_emailinfo, 1); + new->next = od->emailinfo; + od->emailinfo = new; } new->cookie8 = cookie8; new->cookie16 = cookie16; - tlvlist = aim_tlvlist_readnum(bs, aimbs_get16(bs)); + tlvlist = aim_tlvlist_readnum(bs, byte_stream_get16(bs)); tmp = aim_tlv_get16(tlvlist, 0x0080, 1); if (tmp) { @@ -150,8 +149,8 @@ alertitle = aim_tlv_getstr(tlvlist, 0x0005, 1); alerturl = aim_tlv_getstr(tlvlist, 0x000d, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, new, havenewmail, alertitle, (alerturl ? alerturl + 2 : NULL)); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, new, havenewmail, alertitle, (alerturl ? alerturl + 2 : NULL)); aim_tlvlist_free(&tlvlist); @@ -164,51 +163,53 @@ /** * Subtype 0x0016 - Send something or other * - * @param sess The oscar session. + * @param od The oscar session. * @param conn The email connection for this session. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_email_activate(OscarSession *sess) +int +aim_email_activate(OscarData *od) { - OscarConnection *conn; + FlapConnection *conn; FlapFrame *fr; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_ALERT))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ALERT))) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+16))) - return -ENOMEM; - snacid = aim_cachesnac(sess, 0x0018, 0x0016, 0x0000, NULL, 0); + fr = flap_frame_new(od, 0x02, 10+1+16); + snacid = aim_cachesnac(od, 0x0018, 0x0016, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0018, 0x0016, 0x0000, snacid); /* I would guess this tells AIM that you want updates for your mail accounts */ /* ...but I really have no idea */ - aimbs_put8(&fr->data, 0x02); - aimbs_put32(&fr->data, 0x04000000); - aimbs_put32(&fr->data, 0x04000000); - aimbs_put32(&fr->data, 0x04000000); - aimbs_put32(&fr->data, 0x00000000); + byte_stream_put8(&fr->data, 0x02); + byte_stream_put32(&fr->data, 0x04000000); + byte_stream_put32(&fr->data, 0x04000000); + byte_stream_put32(&fr->data, 0x04000000); + byte_stream_put32(&fr->data, 0x00000000); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, fr); return 0; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0007) - return parseinfo(sess, mod, rx, snac, bs); + return parseinfo(od, conn, mod, frame, snac, bs); return 0; } -static void email_shutdown(OscarSession *sess, aim_module_t *mod) +static void +email_shutdown(OscarData *od, aim_module_t *mod) { - while (sess->emailinfo) { - struct aim_emailinfo *tmp = sess->emailinfo; - sess->emailinfo = sess->emailinfo->next; + while (od->emailinfo) + { + struct aim_emailinfo *tmp = od->emailinfo; + od->emailinfo = od->emailinfo->next; free(tmp->cookie16); free(tmp->cookie8); free(tmp->url); @@ -219,9 +220,9 @@ return; } -faim_internal int email_modfirst(OscarSession *sess, aim_module_t *mod) +int +email_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0018; mod->version = 0x0001; mod->toolid = 0x0010;
--- a/src/protocols/oscar/family_auth.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_auth.c Fri Apr 07 05:10:56 2006 +0000 @@ -52,7 +52,8 @@ * @param password Incoming password. * @param encoded Buffer to put encoded password. */ -static int aim_encode_password(const char *password, guint8 *encoded) +static int +aim_encode_password(const char *password, guint8 *encoded) { guint8 encoding_table[] = { #if 0 /* old v1 table */ @@ -77,7 +78,8 @@ #endif #ifdef USE_OLD_MD5 -static int aim_encode_password_md5(const char *password, const char *key, guint8 *digest) +static int +aim_encode_password_md5(const char *password, const char *key, guint8 *digest) { GaimCipher *cipher; GaimCipherContext *context; @@ -94,7 +96,8 @@ return 0; } #else -static int aim_encode_password_md5(const char *password, const char *key, guint8 *digest) +static int +aim_encode_password_md5(const char *password, const char *key, guint8 *digest) { GaimCipher *cipher; GaimCipherContext *context; @@ -118,76 +121,28 @@ } #endif -/* - * The FLAP version is sent by itself at the beginning of authorization - * connections. The FLAP version is also sent before the cookie when connecting - * for other services (BOS, chatnav, chat, etc.). - */ -faim_export int aim_sendflapver(OscarSession *sess, OscarConnection *conn) -{ - FlapFrame *fr; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4))) - return -ENOMEM; - - aimbs_put32(&fr->data, 0x00000001); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/* - * This just pushes the passed cookie onto the passed connection, without - * the SNAC header or any of that. - * - * Very commonly used, as every connection except auth will require this to - * be the first thing you send. - * - */ -faim_export int aim_sendcookie(OscarSession *sess, OscarConnection *conn, const guint16 length, const guint8 *chipsahoy) -{ - FlapFrame *fr; - aim_tlvlist_t *tl = NULL; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4+2+2+length))) - return -ENOMEM; - - aimbs_put32(&fr->data, 0x00000001); - aim_tlvlist_add_raw(&tl, 0x0006, length, chipsahoy); - aim_tlvlist_write(&fr->data, &tl); - aim_tlvlist_free(&tl); - - aim_tx_enqueue(sess, fr); - - return 0; -} - #ifdef USE_XOR_FOR_ICQ /* * Part two of the ICQ hack. Note the ignoring of the key. */ -static int goddamnicq2(OscarSession *sess, OscarConnection *conn, const char *sn, const char *password, ClientInfo *ci) +static int +goddamnicq2(OscarData *od, FlapConnection *conn, const char *sn, const char *password, ClientInfo *ci) { - FlapFrame *fr; + FlapFrame *frame; aim_tlvlist_t *tl = NULL; int passwdlen; guint8 *password_encoded; passwdlen = strlen(password); - if (!(password_encoded = (guint8 *)malloc(passwdlen+1))) - return -ENOMEM; + password_encoded = (guint8 *)malloc(passwdlen+1); if (passwdlen > MAXICQPASSLEN) passwdlen = MAXICQPASSLEN; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 1152))) { - free(password_encoded); - return -ENOMEM; - } + frame = flap_frame_new(od, 0x01, 1152); aim_encode_password(password, password_encoded); - aimbs_put32(&fr->data, 0x00000001); /* FLAP Version */ + byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */ aim_tlvlist_add_str(&tl, 0x0001, sn); aim_tlvlist_add_raw(&tl, 0x0002, passwdlen, password_encoded); @@ -202,12 +157,12 @@ aim_tlvlist_add_str(&tl, 0x000f, ci->lang); aim_tlvlist_add_str(&tl, 0x000e, ci->country); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); free(password_encoded); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -242,9 +197,10 @@ * serverstore = 0x01 * */ -faim_export int aim_send_login(OscarSession *sess, OscarConnection *conn, const char *sn, const char *password, ClientInfo *ci, const char *key) +int +aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, ClientInfo *ci, const char *key) { - FlapFrame *fr; + FlapFrame *frame; aim_tlvlist_t *tl = NULL; guint8 digest[16]; aim_snacid_t snacid; @@ -255,14 +211,13 @@ #ifdef USE_XOR_FOR_ICQ /* If we're signing on an ICQ account then use the older, XOR login method */ if (isdigit(sn[0])) - return goddamnicq2(sess, conn, sn, password, ci); + return goddamnicq2(od, conn, sn, password, ci); #endif - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 1152); - snacid = aim_cachesnac(sess, 0x0017, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0017, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0017, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0017, 0x0002, 0x0000, snacid); aim_tlvlist_add_str(&tl, 0x0001, sn); @@ -302,11 +257,11 @@ */ aim_tlvlist_add_8(&tl, 0x004a, 0x01); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -314,20 +269,20 @@ /* * This is sent back as a general response to the login command. * It can be either an error or a success, depending on the - * presence of certain TLVs. + * presence of certain TLVs. * * The client should check the value passed as errorcode. If * its nonzero, there was an error. */ -static int parse(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +parse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_tlvlist_t *tlvlist; aim_rxcallback_t userfunc; struct aim_authresp_info *info; int ret = 0; - info = (struct aim_authresp_info *)malloc(sizeof(struct aim_authresp_info)); - memset(info, 0, sizeof(struct aim_authresp_info)); + info = g_new0(struct aim_authresp_info, 1); /* * Read block of TLVs. All further data is derived @@ -338,10 +293,10 @@ /* * No matter what, we should have a screen name. */ - memset(sess->sn, 0, sizeof(sess->sn)); + memset(od->sn, 0, sizeof(od->sn)); if (aim_tlv_gettlv(tlvlist, 0x0001, 1)) { info->sn = aim_tlv_getstr(tlvlist, 0x0001, 1); - strncpy(sess->sn, info->sn, sizeof(sess->sn)); + strncpy(od->sn, info->sn, sizeof(od->sn)); } /* @@ -374,7 +329,7 @@ /* * The email address attached to this account * Not available for ICQ or @mac.com logins. - * If you receive this TLV, then you are allowed to use + * If you receive this TLV, then you are allowed to use * family 0x0018 to check the status of your email. * XXX - Not really true! */ @@ -443,10 +398,10 @@ } #endif - sess->authinfo = info; + od->authinfo = info; - if ((userfunc = aim_callhandler(sess, rx->conn, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003))) - ret = userfunc(sess, rx, info); + if ((userfunc = aim_callhandler(od, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003))) + ret = userfunc(od, conn, frame, info); aim_tlvlist_free(&tlvlist); @@ -489,15 +444,14 @@ * being called from the context of aim_rxdispatch()... * */ -static int goddamnicq(OscarSession *sess, OscarConnection *conn, const char *sn) +static int +goddamnicq(OscarData *od, FlapConnection *conn, const char *sn) { - FlapFrame fr; + FlapFrame frame; aim_rxcallback_t userfunc; - fr.conn = conn; - - if ((userfunc = aim_callhandler(sess, conn, 0x0017, 0x0007))) - userfunc(sess, &fr, ""); + if ((userfunc = aim_callhandler(od, 0x0017, 0x0007))) + userfunc(od, conn, &frame, ""); return 0; } @@ -506,34 +460,32 @@ /* * Subtype 0x0006 * - * In AIM 3.5 protocol, the first stage of login is to request login from the - * Authorizer, passing it the screen name for verification. If the name is - * invalid, a 0017/0003 is spit back, with the standard error contents. If - * valid, a 0017/0007 comes back, which is the signal to send it the main - * login command (0017/0002). + * In AIM 3.5 protocol, the first stage of login is to request login from the + * Authorizer, passing it the screen name for verification. If the name is + * invalid, a 0017/0003 is spit back, with the standard error contents. If + * valid, a 0017/0007 comes back, which is the signal to send it the main + * login command (0017/0002). * */ -faim_export int aim_request_login(OscarSession *sess, OscarConnection *conn, const char *sn) +int +aim_request_login(OscarData *od, FlapConnection *conn, const char *sn) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!sess || !conn || !sn) + if (!od || !conn || !sn) return -EINVAL; #ifdef USE_XOR_FOR_ICQ if (isdigit(sn[0])) - return goddamnicq(sess, conn, sn); + return goddamnicq(od, conn, sn); #endif - aim_sendflapver(sess, conn); + frame = flap_frame_new(od, 0x02, 10+2+2+strlen(sn)+8); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(sn)+8 ))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0017, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0017, 0x0006, 0x0000, snacid); aim_tlvlist_add_str(&tl, 0x0001, sn); @@ -543,10 +495,10 @@ /* Unknown. Sent in recent WinAIM clients.*/ aim_tlvlist_add_noval(&tl, 0x005a); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -560,21 +512,22 @@ * Calls the client, which should then use the value to call aim_send_login. * */ -static int keyparse(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +keyparse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int keylen, ret = 1; aim_rxcallback_t userfunc; char *keystr; - keylen = aimbs_get16(bs); - keystr = aimbs_getstr(bs, keylen); + keylen = byte_stream_get16(bs); + keystr = byte_stream_getstr(bs, keylen); - /* XXX - When GiantGrayPanda signed on AIM I got a thing asking me to register - * for the netscape network. This SNAC had a type 0x0058 TLV with length 10. + /* XXX - When GiantGrayPanda signed on AIM I got a thing asking me to register + * for the netscape network. This SNAC had a type 0x0058 TLV with length 10. * Data is 0x0007 0004 3e19 ae1e 0006 0004 0000 0005 */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, keystr); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, keystr); free(keystr); @@ -586,13 +539,14 @@ * * Receive SecurID request. */ -static int got_securid_request(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +got_securid_request(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame); return ret; } @@ -602,66 +556,68 @@ * * Send SecurID response. */ -faim_export int aim_auth_securid_send(OscarSession *sess, const char *securid) +int +aim_auth_securid_send(OscarData *od, const char *securid) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int len; - if (!sess || !(conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH)) || !securid) + if (!od || !(conn = flap_connection_getbytype_all(od, SNAC_FAMILY_AUTH)) || !securid) return -EINVAL; len = strlen(securid); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+len))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+2+len); + + snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_RESPONSE, 0x0000, NULL, 0); + aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_RESPONSE, 0x0000, 0); - snacid = aim_cachesnac(sess, OSCAR_FAMILY_AUTH, OSCAR_SUBTYPE_AUTH_SECURID_RESPONSE, 0x0000, NULL, 0); - aim_putsnac(&fr->data, OSCAR_FAMILY_AUTH, OSCAR_SUBTYPE_AUTH_SECURID_RESPONSE, 0x0000, 0); + byte_stream_put16(&frame->data, len); + byte_stream_putstr(&frame->data, securid); - aimbs_put16(&fr->data, len); - aimbs_putstr(&fr->data, securid); - - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -static void auth_shutdown(OscarSession *sess, aim_module_t *mod) +static void +auth_shutdown(OscarData *od, aim_module_t *mod) { - if (sess->authinfo) { - free(sess->authinfo->sn); - free(sess->authinfo->bosip); - free(sess->authinfo->errorurl); - free(sess->authinfo->email); - free(sess->authinfo->chpassurl); - free(sess->authinfo->latestrelease.name); - free(sess->authinfo->latestrelease.url); - free(sess->authinfo->latestrelease.info); - free(sess->authinfo->latestbeta.name); - free(sess->authinfo->latestbeta.url); - free(sess->authinfo->latestbeta.info); - free(sess->authinfo); + if (od->authinfo != NULL) + { + free(od->authinfo->sn); + free(od->authinfo->bosip); + free(od->authinfo->errorurl); + free(od->authinfo->email); + free(od->authinfo->chpassurl); + free(od->authinfo->latestrelease.name); + free(od->authinfo->latestrelease.url); + free(od->authinfo->latestrelease.info); + free(od->authinfo->latestbeta.name); + free(od->authinfo->latestbeta.url); + free(od->authinfo->latestbeta.info); + free(od->authinfo); } } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0003) - return parse(sess, mod, rx, snac, bs); + return parse(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0007) - return keyparse(sess, mod, rx, snac, bs); + return keyparse(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000a) - return got_securid_request(sess, mod, rx, snac, bs); + return got_securid_request(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int auth_modfirst(OscarSession *sess, aim_module_t *mod) +int +auth_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0017; mod->version = 0x0000; mod->flags = 0;
--- a/src/protocols/oscar/family_bart.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_bart.c Fri Apr 07 05:10:56 2006 +0000 @@ -31,34 +31,33 @@ /** * Subtype 0x0002 - Upload your icon. * - * @param sess The oscar session. - * @param conn The icon connection for this session. + * @param od The oscar session. * @param icon The raw data of the icon image file. * @param iconlen Length of the raw data of the icon image file. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_bart_upload(OscarSession *sess, const guint8 *icon, guint16 iconlen) +int +aim_bart_upload(OscarData *od, const guint8 *icon, guint16 iconlen) { - OscarConnection *conn; + FlapConnection *conn; FlapFrame *fr; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0010)) || !icon || !iconlen) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0010)) || !icon || !iconlen) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2 + 2+iconlen))) - return -ENOMEM; - snacid = aim_cachesnac(sess, 0x0010, 0x0002, 0x0000, NULL, 0); + fr = flap_frame_new(od, 0x02, 10 + 2 + 2+iconlen); + snacid = aim_cachesnac(od, 0x0010, 0x0002, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0010, 0x0002, 0x0000, snacid); /* The reference number for the icon */ - aimbs_put16(&fr->data, 1); + byte_stream_put16(&fr->data, 1); /* The icon */ - aimbs_put16(&fr->data, iconlen); - aimbs_putraw(&fr->data, icon, iconlen); + byte_stream_put16(&fr->data, iconlen); + byte_stream_putraw(&fr->data, icon, iconlen); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, fr); return 0; } @@ -68,19 +67,20 @@ * * You get this honky after you upload a buddy icon. */ -static int uploadack(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +uploadack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; guint16 something, somethingelse; guint8 onemorething; - something = aimbs_get16(bs); - somethingelse = aimbs_get16(bs); - onemorething = aimbs_get8(bs); + something = byte_stream_get16(bs); + somethingelse = byte_stream_get16(bs); + onemorething = byte_stream_get8(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame); return ret; } @@ -88,41 +88,40 @@ /** * Subtype 0x0004 - Request someone's icon. * - * @param sess The oscar session. - * @param conn The icon connection for this session. + * @param od The oscar session. * @param sn The screen name of the person who's icon you are requesting. * @param iconcsum The MD5 checksum of the icon you are requesting. * @param iconcsumlen Length of the MD5 checksum given above. Should be 10 bytes. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_bart_request(OscarSession *sess, const char *sn, guint8 iconcsumtype, const guint8 *iconcsum, guint16 iconcsumlen) +int +aim_bart_request(OscarData *od, const char *sn, guint8 iconcsumtype, const guint8 *iconcsum, guint16 iconcsumlen) { - OscarConnection *conn; + FlapConnection *conn; FlapFrame *fr; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0010)) || !sn || !strlen(sn) || !iconcsum || !iconcsumlen) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0010)) || !sn || !strlen(sn) || !iconcsum || !iconcsumlen) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 4 + 1+iconcsumlen))) - return -ENOMEM; - snacid = aim_cachesnac(sess, 0x0010, 0x0004, 0x0000, NULL, 0); + fr = flap_frame_new(od, 0x02, 10 + 1+strlen(sn) + 4 + 1+iconcsumlen); + snacid = aim_cachesnac(od, 0x0010, 0x0004, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0010, 0x0004, 0x0000, snacid); /* Screen name */ - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); + byte_stream_put8(&fr->data, strlen(sn)); + byte_stream_putstr(&fr->data, sn); /* Some numbers. You like numbers, right? */ - aimbs_put8(&fr->data, 0x01); - aimbs_put16(&fr->data, 0x0001); - aimbs_put8(&fr->data, iconcsumtype); + byte_stream_put8(&fr->data, 0x01); + byte_stream_put16(&fr->data, 0x0001); + byte_stream_put8(&fr->data, iconcsumtype); /* Icon string */ - aimbs_put8(&fr->data, iconcsumlen); - aimbs_putraw(&fr->data, iconcsum, iconcsumlen); + byte_stream_put8(&fr->data, iconcsumlen); + byte_stream_putraw(&fr->data, iconcsum, iconcsumlen); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, fr); return 0; } @@ -132,7 +131,8 @@ * * This is sent in response to a buddy icon request. */ -static int parseicon(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +parseicon(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -140,16 +140,16 @@ guint16 flags, iconlen; guint8 iconcsumtype, iconcsumlen, *iconcsum, *icon; - sn = aimbs_getstr(bs, aimbs_get8(bs)); - flags = aimbs_get16(bs); - iconcsumtype = aimbs_get8(bs); - iconcsumlen = aimbs_get8(bs); - iconcsum = aimbs_getraw(bs, iconcsumlen); - iconlen = aimbs_get16(bs); - icon = aimbs_getraw(bs, iconlen); + sn = byte_stream_getstr(bs, byte_stream_get8(bs)); + flags = byte_stream_get16(bs); + iconcsumtype = byte_stream_get8(bs); + iconcsumlen = byte_stream_get8(bs); + iconcsum = byte_stream_getraw(bs, iconcsumlen); + iconlen = byte_stream_get16(bs); + icon = byte_stream_getraw(bs, iconlen); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, sn, iconcsumtype, iconcsum, iconcsumlen, icon, iconlen); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, sn, iconcsumtype, iconcsum, iconcsumlen, icon, iconlen); free(sn); free(iconcsum); @@ -158,20 +158,20 @@ return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0003) - return uploadack(sess, mod, rx, snac, bs); + return uploadack(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0005) - return parseicon(sess, mod, rx, snac, bs); + return parseicon(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int bart_modfirst(OscarSession *sess, aim_module_t *mod) +int +bart_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0010; mod->version = 0x0001; mod->toolid = 0x0010;
--- a/src/protocols/oscar/family_bos.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_bos.c Fri Apr 07 05:10:56 2006 +0000 @@ -29,13 +29,13 @@ #include <string.h> /* Subtype 0x0002 - Request BOS rights. */ -faim_export int aim_bos_reqrights(OscarSession *sess, OscarConnection *conn) +int aim_bos_reqrights(OscarData *od, FlapConnection *conn) { - return aim_genericreq_n_snacid(sess, conn, 0x0009, 0x0002); + return aim_genericreq_n_snacid(od, conn, 0x0009, 0x0002); } /* Subtype 0x0003 - BOS Rights. */ -static int rights(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_rxcallback_t userfunc; aim_tlvlist_t *tlvlist; @@ -59,8 +59,8 @@ if (aim_tlv_gettlv(tlvlist, 0x0002, 1)) maxdenies = aim_tlv_get16(tlvlist, 0x0002, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, maxpermits, maxdenies); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, maxpermits, maxdenies); aim_tlvlist_free(&tlvlist); @@ -77,9 +77,9 @@ * a bitwise OR of all the user classes you want to see you. * */ -faim_export int aim_bos_setgroupperm(OscarSession *sess, OscarConnection *conn, guint32 mask) +int aim_bos_setgroupperm(OscarData *od, FlapConnection *conn, guint32 mask) { - return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask); + return aim_genericreq_l(od, conn, 0x0009, 0x0004, &mask); } /* @@ -110,9 +110,9 @@ * * XXX ye gods. */ -faim_export int aim_bos_changevisibility(OscarSession *sess, OscarConnection *conn, int changetype, const char *denylist) +int aim_bos_changevisibility(OscarData *od, FlapConnection *conn, int changetype, const char *denylist) { - FlapFrame *fr; + FlapFrame *frame; int packlen = 0; guint16 subtype; char *localcpy = NULL, *tmpptr = NULL; @@ -139,41 +139,38 @@ listcount = aimutil_itemcnt(localcpy, '&'); packlen = aimutil_tokslen(localcpy, 99, '&') + listcount + 9; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, packlen))) { - free(localcpy); - return -ENOMEM; - } + frame = flap_frame_new(od, 0x02, packlen); - snacid = aim_cachesnac(sess, 0x0009, subtype, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0009, subtype, 0x00, snacid); + snacid = aim_cachesnac(od, 0x0009, subtype, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0009, subtype, 0x00, snacid); for (i = 0; (i < (listcount - 1)) && (i < 99); i++) { tmpptr = aimutil_itemindex(localcpy, i, '&'); - aimbs_put8(&fr->data, strlen(tmpptr)); - aimbs_putstr(&fr->data, tmpptr); + byte_stream_put8(&frame->data, strlen(tmpptr)); + byte_stream_putstr(&frame->data, tmpptr); free(tmpptr); } free(localcpy); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0003) - return rights(sess, mod, rx, snac, bs); + return rights(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int bos_modfirst(OscarSession *sess, aim_module_t *mod) +int +bos_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0009; mod->version = 0x0001; mod->toolid = 0x0110;
--- a/src/protocols/oscar/family_buddy.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_buddy.c Fri Apr 07 05:10:56 2006 +0000 @@ -33,16 +33,18 @@ * Request Buddy List rights. * */ -faim_export int aim_buddylist_reqrights(OscarSession *sess, OscarConnection *conn) +int +aim_buddylist_reqrights(OscarData *od, FlapConnection *conn) { - return aim_genericreq_n_snacid(sess, conn, 0x0003, 0x0002); + return aim_genericreq_n_snacid(od, conn, 0x0003, 0x0002); } /* * Subtype 0x0003 - Rights. * */ -static int rights(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_rxcallback_t userfunc; aim_tlvlist_t *tlvlist; @@ -77,8 +79,8 @@ * ICQ only? */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, maxbuddies, maxwatchers); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, maxbuddies, maxwatchers); aim_tlvlist_free(&tlvlist); @@ -92,24 +94,24 @@ * XXX This should just be an extension of setbuddylist() * */ -faim_export int aim_buddylist_addbuddy(OscarSession *sess, OscarConnection *conn, const char *sn) +int +aim_buddylist_addbuddy(OscarData *od, FlapConnection *conn, const char *sn) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; if (!sn || !strlen(sn)) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+1+strlen(sn)); + + snacid = aim_cachesnac(od, 0x0003, 0x0004, 0x0000, sn, strlen(sn)+1); + aim_putsnac(&frame->data, 0x0003, 0x0004, 0x0000, snacid); - snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, sn, strlen(sn)+1); - aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid); + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); - - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -124,9 +126,10 @@ * XXX Clean this up. * */ -faim_export int aim_buddylist_set(OscarSession *sess, OscarConnection *conn, const char *buddy_list) +int +aim_buddylist_set(OscarData *od, FlapConnection *conn, const char *buddy_list) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; int len = 0; char *localcpy = NULL; @@ -141,11 +144,10 @@ tmpptr = strtok(NULL, "&"); } - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+len))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+len); - snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0003, 0x0004, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0003, 0x0004, 0x0000, snacid); strncpy(localcpy, buddy_list, strlen(buddy_list) + 1); @@ -153,12 +155,12 @@ gaim_debug_misc("oscar", "---adding: %s (%d)\n", tmpptr, strlen(tmpptr)); - aimbs_put8(&fr->data, strlen(tmpptr)); - aimbs_putstr(&fr->data, tmpptr); + byte_stream_put8(&frame->data, strlen(tmpptr)); + byte_stream_putstr(&frame->data, tmpptr); tmpptr = strtok(NULL, "&"); } - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); free(localcpy); @@ -172,79 +174,24 @@ * the same as setbuddylist() but with a different snac subtype). * */ -faim_export int aim_buddylist_removebuddy(OscarSession *sess, OscarConnection *conn, const char *sn) +int +aim_buddylist_removebuddy(OscarData *od, FlapConnection *conn, const char *sn) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; if (!sn || !strlen(sn)) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0003, 0x0005, 0x0000, sn, strlen(sn)+1); - aim_putsnac(&fr->data, 0x0003, 0x0005, 0x0000, snacid); - - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); - - aim_tx_enqueue(sess, fr); - - return 0; -} + frame = flap_frame_new(od, 0x02, 10+1+strlen(sn)); -/* - * Subtype 0x000b - * - * XXX Why would we send this? - * - */ -faim_export int aim_buddylist_oncoming(OscarSession *sess, OscarConnection *conn, aim_userinfo_t *info) -{ - FlapFrame *fr; - aim_snacid_t snacid; - - if (!sess || !conn || !info) - return -EINVAL; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0003, 0x000b, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0003, 0x0005, 0x0000, sn, strlen(sn)+1); + aim_putsnac(&frame->data, 0x0003, 0x0005, 0x0000, snacid); - aim_putsnac(&fr->data, 0x0003, 0x000b, 0x0000, snacid); - aim_putuserinfo(&fr->data, info); - - aim_tx_enqueue(sess, fr); - - return 0; -} + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); -/* - * Subtype 0x000c - * - * XXX Why would we send this? - * - */ -faim_export int aim_buddylist_offgoing(OscarSession *sess, OscarConnection *conn, const char *sn) -{ - FlapFrame *fr; - aim_snacid_t snacid; - - if (!sess || !conn || !sn) - return -EINVAL; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0003, 0x000c, 0x0000, NULL, 0); - - aim_putsnac(&fr->data, 0x0003, 0x000c, 0x0000, snacid); - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); - - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -260,38 +207,39 @@ * it is still in a format parsable by aim_info_extract(). * */ -static int buddychange(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +buddychange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_userinfo_t userinfo; aim_rxcallback_t userfunc; - aim_info_extract(sess, bs, &userinfo); + aim_info_extract(od, bs, &userinfo); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, &userinfo); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, &userinfo); if (snac->subtype == 0x000b) - aim_locate_requestuserinfo(sess, userinfo.sn); + aim_locate_requestuserinfo(od, userinfo.sn); aim_info_free(&userinfo); return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0003) - return rights(sess, mod, rx, snac, bs); + return rights(od, conn, mod, frame, snac, bs); else if ((snac->subtype == 0x000b) || (snac->subtype == 0x000c)) - return buddychange(sess, mod, rx, snac, bs); + return buddychange(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int buddylist_modfirst(OscarSession *sess, aim_module_t *mod) +int +buddylist_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0003; mod->version = 0x0001; mod->toolid = 0x0110;
--- a/src/protocols/oscar/family_chat.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_chat.c Fri Apr 07 05:10:56 2006 +0000 @@ -28,13 +28,15 @@ #include <string.h> /* Stored in the ->internal of chat connections */ -struct chatconnpriv { +struct chatconnpriv +{ guint16 exchange; char *name; guint16 instance; }; -faim_internal void oscar_connection_destroy_chat(OscarSession *sess, OscarConnection *conn) +void +flap_connection_destroy_chat(OscarData *od, FlapConnection *conn) { struct chatconnpriv *ccp = (struct chatconnpriv *)conn->internal; @@ -45,14 +47,15 @@ return; } -faim_export char *aim_chat_getname(OscarConnection *conn) +char * +aim_chat_getname(FlapConnection *conn) { struct chatconnpriv *ccp; if (!conn) return NULL; - if (conn->type != AIM_CONN_TYPE_CHAT) + if (conn->type != SNAC_FAMILY_CHAT) return NULL; ccp = (struct chatconnpriv *)conn->internal; @@ -61,19 +64,20 @@ } /* XXX get this into conn.c -- evil!! */ -faim_export OscarConnection *aim_chat_getconn(OscarSession *sess, const char *name) +FlapConnection * +aim_chat_getconn(OscarData *od, const char *name) { GList *cur; - for (cur = sess->oscar_connections; cur; cur = cur->next) + for (cur = od->oscar_connections; cur; cur = cur->next) { - OscarConnection *conn; + FlapConnection *conn; struct chatconnpriv *ccp; conn = cur->data; ccp = (struct chatconnpriv *)conn->internal; - if (conn->type != AIM_CONN_TYPE_CHAT) + if (conn->type != SNAC_FAMILY_CHAT) continue; if (!conn->internal) { gaim_debug_misc("oscar", "faim: chat: chat connection with no name! (fd = %d)\n", conn->fd); @@ -87,7 +91,8 @@ return NULL; } -faim_export int aim_chat_attachname(OscarConnection *conn, guint16 exchange, const char *roomname, guint16 instance) +int +aim_chat_attachname(FlapConnection *conn, guint16 exchange, const char *roomname, guint16 instance) { struct chatconnpriv *ccp; @@ -97,8 +102,7 @@ if (conn->internal) free(conn->internal); - if (!(ccp = malloc(sizeof(struct chatconnpriv)))) - return -ENOMEM; + ccp = g_new(struct chatconnpriv, 1); ccp->exchange = exchange; ccp->name = strdup(roomname); @@ -109,29 +113,31 @@ return 0; } -faim_internal int aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo) +int +aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo) { int namelen; if (!bs || !outinfo) return 0; - outinfo->exchange = aimbs_get16(bs); - namelen = aimbs_get8(bs); - outinfo->name = aimbs_getstr(bs, namelen); - outinfo->instance = aimbs_get16(bs); + outinfo->exchange = byte_stream_get16(bs); + namelen = byte_stream_get8(bs); + outinfo->name = byte_stream_getstr(bs, namelen); + outinfo->instance = byte_stream_get16(bs); return 0; } -faim_export int aim_chat_leaveroom(OscarSession *sess, const char *name) +int +aim_chat_leaveroom(OscarData *od, const char *name) { - OscarConnection *conn; + FlapConnection *conn; - if (!(conn = aim_chat_getconn(sess, name))) + if (!(conn = aim_chat_getconn(od, name))) return -ENOENT; - aim_conn_close(sess, conn); + flap_connection_close(od, conn); return 0; } @@ -144,7 +150,8 @@ * - Language (English) * */ -static int infoupdate(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +infoupdate(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_userinfo_t *userinfo = NULL; aim_rxcallback_t userfunc; @@ -163,14 +170,14 @@ aim_chat_readroominfo(bs, &roominfo); - detaillevel = aimbs_get8(bs); + detaillevel = byte_stream_get8(bs); if (detaillevel != 0x02) { gaim_debug_misc("oscar", "faim: chat_roomupdateinfo: detail level %d not supported\n", detaillevel); return 1; } - tlvcount = aimbs_get16(bs); + tlvcount = byte_stream_get16(bs); /* * Everything else are TLVs. @@ -202,10 +209,10 @@ /* Allocate enough userinfo structs for all occupants */ userinfo = calloc(usercount, sizeof(aim_userinfo_t)); - aim_bstream_init(&occbs, tmptlv->value, tmptlv->length); + byte_stream_init(&occbs, tmptlv->value, tmptlv->length); while (curoccupant < usercount) - aim_info_extract(sess, &occbs, &userinfo[curoccupant++]); + aim_info_extract(od, &occbs, &userinfo[curoccupant++]); } /* @@ -289,9 +296,9 @@ if (aim_tlv_gettlv(tlvlist, 0x000da, 1)) maxvisiblemsglen = aim_tlv_get16(tlvlist, 0x00da, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { - ret = userfunc(sess, - rx, + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) { + ret = userfunc(od, conn, + frame, &roominfo, roomname, usercount, @@ -319,20 +326,21 @@ } /* Subtypes 0x0003 and 0x0004 */ -static int userlistchange(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +userlistchange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_userinfo_t *userinfo = NULL; aim_rxcallback_t userfunc; int curcount = 0, ret = 0; - while (aim_bstream_empty(bs)) { + while (byte_stream_empty(bs)) { curcount++; userinfo = realloc(userinfo, curcount * sizeof(aim_userinfo_t)); - aim_info_extract(sess, bs, &userinfo[curcount-1]); + aim_info_extract(od, bs, &userinfo[curcount-1]); } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, curcount, userinfo); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, curcount, userinfo); aim_info_free(userinfo); free(userinfo); @@ -352,23 +360,23 @@ * * XXX convert this to use tlvchains */ -faim_export int aim_chat_send_im(OscarSession *sess, OscarConnection *conn, guint16 flags, const gchar *msg, int msglen, const char *encoding, const char *language) +int +aim_chat_send_im(OscarData *od, FlapConnection *conn, guint16 flags, const gchar *msg, int msglen, const char *encoding, const char *language) { int i; - FlapFrame *fr; + FlapFrame *frame; IcbmCookie *cookie; aim_snacid_t snacid; guint8 ckstr[8]; aim_tlvlist_t *otl = NULL, *itl = NULL; - if (!sess || !conn || !msg || (msglen <= 0)) + if (!od || !conn || !msg || (msglen <= 0)) return 0; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 1152); - snacid = aim_cachesnac(sess, 0x000e, 0x0005, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x000e, 0x0005, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x000e, 0x0005, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x000e, 0x0005, 0x0000, snacid); /* * Cookie @@ -382,11 +390,11 @@ cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_CHAT, NULL); cookie->data = NULL; /* XXX store something useful here */ - aim_cachecookie(sess, cookie); + aim_cachecookie(od, cookie); /* ICBM Header */ - aimbs_putraw(&fr->data, ckstr, 8); /* Cookie */ - aimbs_put16(&fr->data, 0x0003); /* Channel */ + byte_stream_putraw(&frame->data, ckstr, 8); /* Cookie */ + byte_stream_put16(&frame->data, 0x0003); /* Channel */ /* * Type 1: Flag meaning this message is destined to the room. @@ -431,12 +439,12 @@ */ aim_tlvlist_add_frozentlvlist(&otl, 0x0005, &itl); - aim_tlvlist_write(&fr->data, &otl); + aim_tlvlist_write(&frame->data, &otl); aim_tlvlist_free(&itl); aim_tlvlist_free(&otl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -466,7 +474,8 @@ * possibly others * */ -static int incomingim_ch3(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +incomingim_ch3(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0, i; aim_rxcallback_t userfunc; @@ -485,9 +494,9 @@ * Read ICBM Cookie. */ for (i = 0; i < 8; i++) - cookie[i] = aimbs_get8(bs); + cookie[i] = byte_stream_get8(bs); - if ((ck = aim_uncachecookie(sess, cookie, AIM_COOKIETYPE_CHAT))) { + if ((ck = aim_uncachecookie(od, cookie, AIM_COOKIETYPE_CHAT))) { free(ck->data); free(ck); } @@ -498,7 +507,7 @@ * Channel 0x0003 is used for chat messages. * */ - channel = aimbs_get16(bs); + channel = byte_stream_get16(bs); if (channel != 0x0003) { gaim_debug_misc("oscar", "faim: chat_incoming: unknown channel! (0x%04x)\n", channel); @@ -519,8 +528,8 @@ userinfotlv = aim_tlv_gettlv(otl, 0x0003, 1); - aim_bstream_init(&tbs, userinfotlv->value, userinfotlv->length); - aim_info_extract(sess, &tbs, &userinfo); + byte_stream_init(&tbs, userinfotlv->value, userinfotlv->length); + aim_info_extract(od, &tbs, &userinfo); } #if 0 @@ -542,7 +551,7 @@ ByteStream tbs; msgblock = aim_tlv_gettlv(otl, 0x0005, 1); - aim_bstream_init(&tbs, msgblock->value, msgblock->length); + byte_stream_init(&tbs, msgblock->value, msgblock->length); itl = aim_tlvlist_read(&tbs); /* @@ -568,8 +577,8 @@ aim_tlvlist_free(&itl); } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, &userinfo, len, msg, encoding, language); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, &userinfo, len, msg, encoding, language); aim_info_free(&userinfo); free(msg); @@ -578,22 +587,22 @@ return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0002) - return infoupdate(sess, mod, rx, snac, bs); + return infoupdate(od, conn, mod, frame, snac, bs); else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004)) - return userlistchange(sess, mod, rx, snac, bs); + return userlistchange(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0006) - return incomingim_ch3(sess, mod, rx, snac, bs); + return incomingim_ch3(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int chat_modfirst(OscarSession *sess, aim_module_t *mod) +int +chat_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x000e; mod->version = 0x0001; mod->toolid = 0x0010;
--- a/src/protocols/oscar/family_chatnav.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_chatnav.c Fri Apr 07 05:10:56 2006 +0000 @@ -35,36 +35,35 @@ * conn must be a chatnav connection! * */ -faim_export int aim_chatnav_reqrights(OscarSession *sess, OscarConnection *conn) +int aim_chatnav_reqrights(OscarData *od, FlapConnection *conn) { - return aim_genericreq_n_snacid(sess, conn, 0x000d, 0x0002); + return aim_genericreq_n_snacid(od, conn, 0x000d, 0x0002); } /* * Subtype 0x0008 */ -faim_export int aim_chatnav_createroom(OscarSession *sess, OscarConnection *conn, const char *name, guint16 exchange) +int aim_chatnav_createroom(OscarData *od, FlapConnection *conn, const char *name, guint16 exchange) { static const char ck[] = {"create"}; static const char lang[] = {"en"}; static const char charset[] = {"us-ascii"}; - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 1152); - snacid = aim_cachesnac(sess, 0x000d, 0x0008, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x000d, 0x0008, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x000d, 0x0008, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x000d, 0x0008, 0x0000, snacid); /* exchange */ - aimbs_put16(&fr->data, exchange); + byte_stream_put16(&frame->data, exchange); /* * This looks to be a big hack. You'll note that this entire * SNAC is just a room info structure, but the hard room name, - * here, is set to "create". + * here, is set to "create". * * Either this goes on the "list of questions concerning * why-the-hell-did-you-do-that", or this value is completely @@ -72,36 +71,37 @@ * AOL style, I'm going to guess that it is the latter, and that * the value of the room name in create requests is ignored. */ - aimbs_put8(&fr->data, strlen(ck)); - aimbs_putstr(&fr->data, ck); + byte_stream_put8(&frame->data, strlen(ck)); + byte_stream_putstr(&frame->data, ck); - /* + /* * instance - * + * * Setting this to 0xffff apparently assigns the last instance. * */ - aimbs_put16(&fr->data, 0xffff); + byte_stream_put16(&frame->data, 0xffff); /* detail level */ - aimbs_put8(&fr->data, 0x01); + byte_stream_put8(&frame->data, 0x01); aim_tlvlist_add_str(&tl, 0x00d3, name); aim_tlvlist_add_str(&tl, 0x00d6, charset); aim_tlvlist_add_str(&tl, 0x00d7, lang); /* tlvcount */ - aimbs_put16(&fr->data, aim_tlvlist_count(&tl)); - aim_tlvlist_write(&fr->data, &tl); + byte_stream_put16(&frame->data, aim_tlvlist_count(&tl)); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -static int parseinfo_perms(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs, aim_snac_t *snac2) +static int +parseinfo_perms(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs, aim_snac_t *snac2) { aim_rxcallback_t userfunc; int ret = 0; @@ -113,30 +113,30 @@ tlvlist = aim_tlvlist_read(bs); - /* + /* * Type 0x0002: Maximum concurrent rooms. - */ + */ if (aim_tlv_gettlv(tlvlist, 0x0002, 1)) maxrooms = aim_tlv_get8(tlvlist, 0x0002, 1); - /* + /* * Type 0x0003: Exchange information * * There can be any number of these, each one - * representing another exchange. - * + * representing another exchange. + * */ for (curexchange = 0; ((exchangetlv = aim_tlv_gettlv(tlvlist, 0x0003, curexchange+1))); ) { ByteStream tbs; - aim_bstream_init(&tbs, exchangetlv->value, exchangetlv->length); + byte_stream_init(&tbs, exchangetlv->value, exchangetlv->length); curexchange++; exchanges = realloc(exchanges, curexchange * sizeof(struct aim_chat_exchangeinfo)); /* exchange number */ - exchanges[curexchange-1].number = aimbs_get16(&tbs); + exchanges[curexchange-1].number = byte_stream_get16(&tbs); innerlist = aim_tlvlist_read(&tbs); #if 0 @@ -213,7 +213,7 @@ /* * Type 0x00d2: Maximum Occupancy? */ - if (aim_tlv_gettlv(innerlist, 0x00d2, 1)) { + if (aim_tlv_gettlv(innerlist, 0x00d2, 1)) { /* Unhandled */ } #endif @@ -221,7 +221,7 @@ /* * Type 0x00d3: Exchange Description */ - if (aim_tlv_gettlv(innerlist, 0x00d3, 1)) + if (aim_tlv_gettlv(innerlist, 0x00d3, 1)) exchanges[curexchange-1].name = aim_tlv_getstr(innerlist, 0x00d3, 1); else exchanges[curexchange-1].name = NULL; @@ -241,7 +241,7 @@ * 0 Creation not allowed * 1 Room creation allowed * 2 Exchange creation allowed - * + * */ if (aim_tlv_gettlv(innerlist, 0x00d5, 1)) { guint8 createperms; @@ -251,32 +251,32 @@ /* * Type 0x00d6: Character Set (First Time) - */ - if (aim_tlv_gettlv(innerlist, 0x00d6, 1)) + */ + if (aim_tlv_gettlv(innerlist, 0x00d6, 1)) exchanges[curexchange-1].charset1 = aim_tlv_getstr(innerlist, 0x00d6, 1); else exchanges[curexchange-1].charset1 = NULL; - + /* * Type 0x00d7: Language (First Time) - */ - if (aim_tlv_gettlv(innerlist, 0x00d7, 1)) + */ + if (aim_tlv_gettlv(innerlist, 0x00d7, 1)) exchanges[curexchange-1].lang1 = aim_tlv_getstr(innerlist, 0x00d7, 1); else exchanges[curexchange-1].lang1 = NULL; /* * Type 0x00d8: Character Set (Second Time) - */ - if (aim_tlv_gettlv(innerlist, 0x00d8, 1)) + */ + if (aim_tlv_gettlv(innerlist, 0x00d8, 1)) exchanges[curexchange-1].charset2 = aim_tlv_getstr(innerlist, 0x00d8, 1); else exchanges[curexchange-1].charset2 = NULL; /* * Type 0x00d9: Language (Second Time) - */ - if (aim_tlv_gettlv(innerlist, 0x00d9, 1)) + */ + if (aim_tlv_gettlv(innerlist, 0x00d9, 1)) exchanges[curexchange-1].lang2 = aim_tlv_getstr(innerlist, 0x00d9, 1); else exchanges[curexchange-1].lang2 = NULL; @@ -296,8 +296,8 @@ /* * Call client. */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, snac2->type, maxrooms, curexchange, exchanges); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, snac2->type, maxrooms, curexchange, exchanges); for (curexchange--; curexchange >= 0; curexchange--) { free(exchanges[curexchange].name); @@ -312,7 +312,8 @@ return ret; } -static int parseinfo_create(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs, aim_snac_t *snac2) +static int +parseinfo_create(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs, aim_snac_t *snac2) { aim_rxcallback_t userfunc; aim_tlvlist_t *tlvlist, *innerlist; @@ -333,13 +334,13 @@ return 0; } - aim_bstream_init(&bbbs, bigblock->value, bigblock->length); + byte_stream_init(&bbbs, bigblock->value, bigblock->length); - exchange = aimbs_get16(&bbbs); - cklen = aimbs_get8(&bbbs); - ck = aimbs_getstr(&bbbs, cklen); - instance = aimbs_get16(&bbbs); - detaillevel = aimbs_get8(&bbbs); + exchange = byte_stream_get16(&bbbs); + cklen = byte_stream_get8(&bbbs); + ck = byte_stream_getstr(&bbbs, cklen); + instance = byte_stream_get16(&bbbs); + detaillevel = byte_stream_get8(&bbbs); if (detaillevel != 0x02) { gaim_debug_misc("oscar", "unknown detaillevel in create room response (0x%02x)\n", detaillevel); @@ -348,7 +349,7 @@ return 0; } - unknown = aimbs_get16(&bbbs); + unknown = byte_stream_get16(&bbbs); innerlist = aim_tlvlist_read(&bbbs); @@ -373,8 +374,8 @@ if (aim_tlv_gettlv(innerlist, 0x00d5, 1)) createperms = aim_tlv_get8(innerlist, 0x00d5, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { - ret = userfunc(sess, rx, snac2->type, fqcn, instance, exchange, flags, createtime, maxmsglen, maxoccupancy, createperms, unknown, name, ck); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) { + ret = userfunc(od, conn, frame, snac2->type, fqcn, instance, exchange, flags, createtime, maxmsglen, maxoccupancy, createperms, unknown, name, ck); } free(ck); @@ -389,7 +390,7 @@ /* * Subtype 0x0009 * - * Since multiple things can trigger this callback, we must lookup the + * Since multiple things can trigger this callback, we must lookup the * snacid to determine the original snac subtype that was called. * * XXX This isn't really how this works. But this is: Every d/9 response @@ -399,17 +400,18 @@ * Instance Info = 4 * Nav Short Desc = 8 * Nav Instance Info = 16 - * And then everything is really asynchronous. There is no specific + * And then everything is really asynchronous. There is no specific * attachment of a response to a create room request, for example. Creating * the room yields no different a response than requesting the room's info. * */ -static int parseinfo(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +parseinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_snac_t *snac2; int ret = 0; - if (!(snac2 = aim_remsnac(sess, snac->id))) { + if (!(snac2 = aim_remsnac(od, snac->id))) { gaim_debug_misc("oscar", "faim: chatnav_parse_info: received response to unknown request! (%08lx)\n", snac->id); return 0; } @@ -423,7 +425,7 @@ * We now know what the original SNAC subtype was. */ if (snac2->type == 0x0002) /* request chat rights */ - ret = parseinfo_perms(sess, mod, rx, snac, bs, snac2); + ret = parseinfo_perms(od, conn, mod, frame, snac, bs, snac2); else if (snac2->type == 0x0003) /* request exchange info */ gaim_debug_misc("oscar", "chatnav_parse_info: resposne to exchange info\n"); else if (snac2->type == 0x0004) /* request room info */ @@ -435,7 +437,7 @@ else if (snac2->type == 0x0007) /* search for a room */ gaim_debug_misc("oscar", "chatnav_parse_info: search results\n"); else if (snac2->type == 0x0008) /* create room */ - ret = parseinfo_create(sess, mod, rx, snac, bs, snac2); + ret = parseinfo_create(od, conn, mod, frame, snac, bs, snac2); else gaim_debug_misc("oscar", "chatnav_parse_info: unknown request subtype (%04x)\n", snac2->type); @@ -446,18 +448,18 @@ return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0009) - return parseinfo(sess, mod, rx, snac, bs); + return parseinfo(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int chatnav_modfirst(OscarSession *sess, aim_module_t *mod) +int +chatnav_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x000d; mod->version = 0x0001; mod->toolid = 0x0010;
--- a/src/protocols/oscar/family_feedbag.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_feedbag.c Fri Apr 07 05:10:56 2006 +0000 @@ -81,8 +81,7 @@ if (newlen > 0) { guint8 *newdata; - if (!(newdata = (guint8 *)malloc((newlen)*sizeof(guint8)))) - return NULL; + newdata = (guint8 *)malloc((newlen)*sizeof(guint8)); newlen = 0; if (group->gid == 0x0000) { for (cur=list; cur; cur=cur->next) @@ -105,7 +104,7 @@ * Locally add a new item to the given item list. * * @param list A pointer to a pointer to the current list of items. - * @param name A null terminated string of the name of the new item, or NULL if the + * @param name A null terminated string of the name of the new item, or NULL if the * item should have no name. * @param gid The group ID# you want the new item to have, or 0xFFFF if we should pick something. * @param bid The buddy ID# you want the new item to have, or 0xFFFF if we should pick something. @@ -121,8 +120,7 @@ if (!list) return NULL; - if (!(new = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) - return NULL; + new = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)); /* Set the name */ if (name) { @@ -268,7 +266,7 @@ * @param bid The buddy ID# of the desired item. * @return Return a pointer to the item if found, else return NULL; */ -faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid) +struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid) { struct aim_ssi_item *cur; for (cur=list; cur; cur=cur->next) @@ -287,7 +285,7 @@ * @param type The type of the desired item. * @return Return a pointer to the item if found, else return NULL. */ -faim_export struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, guint16 type) +struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, guint16 type) { struct aim_ssi_item *cur; if (!list) @@ -332,7 +330,7 @@ * @param sn The group name of the desired item. * @return Return a pointer to the name of the item if found, else return NULL; */ -faim_export struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn) +struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn) { struct aim_ssi_item *cur; if (!list || !sn) @@ -350,7 +348,7 @@ * @param bn The buddy name of the desired item. * @return Return a pointer to the name of the item if found, else return NULL; */ -faim_export char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn) +char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn) { struct aim_ssi_item *cur, *curg; if (!list || !sn) @@ -368,7 +366,7 @@ * @param list A pointer to the current list of items. * @return Return the current SSI permit deny setting, or 0 if no setting was found. */ -faim_export int aim_ssi_getpermdeny(struct aim_ssi_item *list) +int aim_ssi_getpermdeny(struct aim_ssi_item *list) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO); if (cur) { @@ -387,7 +385,7 @@ * @param list A pointer to the current list of items. * @return Return the current visibility mask. */ -faim_export guint32 aim_ssi_getpresence(struct aim_ssi_item *list) +guint32 aim_ssi_getpresence(struct aim_ssi_item *list) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS); if (cur) { @@ -404,11 +402,11 @@ * @param list A pointer to the current list of items. * @param gn The group of the buddy. * @param sn The name of the buddy. - * @return A pointer to a NULL terminated string that is the buddy's + * @return A pointer to a NULL terminated string that is the buddy's * alias, or NULL if the buddy has no alias. You should free * this returned value! */ -faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn) +char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY); if (cur) { @@ -429,11 +427,11 @@ * @param list A pointer to the current list of items. * @param gn The group of the buddy. * @param sn The name of the buddy. - * @return A pointer to a NULL terminated string that is the buddy's + * @return A pointer to a NULL terminated string that is the buddy's * comment, or NULL if the buddy has no comment. You should free * this returned value! */ -faim_export char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn) +char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY); if (cur) { @@ -456,7 +454,7 @@ * @param sn The name of the buddy. * @return 1 if you are waiting for authorization; 0 if you are not */ -faim_export int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn) +int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY); if (cur) { @@ -470,100 +468,100 @@ * If there are changes, then create temporary items and * call addmoddel. * - * @param sess The oscar session. + * @param od The oscar session. * @return Return 0 if no errors, otherwise return the error number. */ -static int aim_ssi_sync(OscarSession *sess) +static int aim_ssi_sync(OscarData *od) { struct aim_ssi_item *cur1, *cur2; struct aim_ssi_tmp *cur, *new; - if (!sess) + if (!od) return -EINVAL; /* If we're waiting for an ack, we shouldn't do anything else */ - if (sess->ssi.waiting_for_ack) + if (od->ssi.waiting_for_ack) return 0; /* - * Compare the 2 lists and create an aim_ssi_tmp for each difference. - * We should only send either additions, modifications, or deletions - * before waiting for an acknowledgement. So first do deletions, then - * additions, then modifications. Also, both the official and the local - * list should be in ascending numerical order for the group ID#s and the + * Compare the 2 lists and create an aim_ssi_tmp for each difference. + * We should only send either additions, modifications, or deletions + * before waiting for an acknowledgement. So first do deletions, then + * additions, then modifications. Also, both the official and the local + * list should be in ascending numerical order for the group ID#s and the * buddy ID#s, which makes things more efficient. I think. */ /* Additions */ - if (!sess->ssi.pending) { - for (cur1=sess->ssi.local; cur1; cur1=cur1->next) { - if (!aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid)) { + if (!od->ssi.pending) { + for (cur1=od->ssi.local; cur1; cur1=cur1->next) { + if (!aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid)) { new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp)); - new->action = OSCAR_SUBTYPE_FEEDBAG_ADD; + new->action = SNAC_SUBTYPE_FEEDBAG_ADD; new->ack = 0xffff; new->name = NULL; new->item = cur1; new->next = NULL; - if (sess->ssi.pending) { - for (cur=sess->ssi.pending; cur->next; cur=cur->next); + if (od->ssi.pending) { + for (cur=od->ssi.pending; cur->next; cur=cur->next); cur->next = new; } else - sess->ssi.pending = new; + od->ssi.pending = new; } } } /* Deletions */ - if (!sess->ssi.pending) { - for (cur1=sess->ssi.official; cur1; cur1=cur1->next) { - if (!aim_ssi_itemlist_find(sess->ssi.local, cur1->gid, cur1->bid)) { + if (!od->ssi.pending) { + for (cur1=od->ssi.official; cur1; cur1=cur1->next) { + if (!aim_ssi_itemlist_find(od->ssi.local, cur1->gid, cur1->bid)) { new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp)); - new->action = OSCAR_SUBTYPE_FEEDBAG_DEL; + new->action = SNAC_SUBTYPE_FEEDBAG_DEL; new->ack = 0xffff; new->name = NULL; new->item = cur1; new->next = NULL; - if (sess->ssi.pending) { - for (cur=sess->ssi.pending; cur->next; cur=cur->next); + if (od->ssi.pending) { + for (cur=od->ssi.pending; cur->next; cur=cur->next); cur->next = new; } else - sess->ssi.pending = new; + od->ssi.pending = new; } } } /* Modifications */ - if (!sess->ssi.pending) { - for (cur1=sess->ssi.local; cur1; cur1=cur1->next) { - cur2 = aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid); + if (!od->ssi.pending) { + for (cur1=od->ssi.local; cur1; cur1=cur1->next) { + cur2 = aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid); if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) { new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp)); - new->action = OSCAR_SUBTYPE_FEEDBAG_MOD; + new->action = SNAC_SUBTYPE_FEEDBAG_MOD; new->ack = 0xffff; new->name = NULL; new->item = cur1; new->next = NULL; - if (sess->ssi.pending) { - for (cur=sess->ssi.pending; cur->next; cur=cur->next); + if (od->ssi.pending) { + for (cur=od->ssi.pending; cur->next; cur=cur->next); cur->next = new; } else - sess->ssi.pending = new; + od->ssi.pending = new; } } } /* We're out of stuff to do, so tell the AIM servers we're done and exit */ - if (!sess->ssi.pending) { - aim_ssi_modend(sess); + if (!od->ssi.pending) { + aim_ssi_modend(od); return 0; } /* Make sure we don't send anything else between now * and when we receive the ack for the following operation */ - sess->ssi.waiting_for_ack = 1; + od->ssi.waiting_for_ack = 1; /* Now go mail off our data and wait 4 to 6 weeks */ - aim_ssi_addmoddel(sess); + aim_ssi_addmoddel(od); return 0; } @@ -573,15 +571,15 @@ * * This doesn't remove it from the server, that's different. * - * @param sess The oscar session. + * @param od The oscar odion. * @return Return 0 if no errors, otherwise return the error number. */ -static int aim_ssi_freelist(OscarSession *sess) +static int aim_ssi_freelist(OscarData *od) { struct aim_ssi_item *cur, *del; struct aim_ssi_tmp *curtmp, *deltmp; - cur = sess->ssi.official; + cur = od->ssi.official; while (cur) { del = cur; cur = cur->next; @@ -590,7 +588,7 @@ free(del); } - cur = sess->ssi.local; + cur = od->ssi.local; while (cur) { del = cur; cur = cur->next; @@ -599,18 +597,18 @@ free(del); } - curtmp = sess->ssi.pending; + curtmp = od->ssi.pending; while (curtmp) { deltmp = curtmp; curtmp = curtmp->next; free(deltmp); } - sess->ssi.numitems = 0; - sess->ssi.official = NULL; - sess->ssi.local = NULL; - sess->ssi.pending = NULL; - sess->ssi.timestamp = (time_t)0; + od->ssi.numitems = 0; + od->ssi.official = NULL; + od->ssi.local = NULL; + od->ssi.pending = NULL; + od->ssi.timestamp = (time_t)0; return 0; } @@ -618,18 +616,18 @@ /** * Delete all SSI data. * - * @param sess The oscar session. + * @param od The oscar odion. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_deletelist(OscarSession *sess) +int aim_ssi_deletelist(OscarData *od) { struct aim_ssi_item *cur, *del; - if (!sess) + if (!od) return -EINVAL; /* Free the local list */ - cur = sess->ssi.local; + cur = od->ssi.local; while (cur) { del = cur; cur = cur->next; @@ -637,10 +635,10 @@ aim_tlvlist_free(&del->data); free(del); } - sess->ssi.local = NULL; + od->ssi.local = NULL; /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -651,14 +649,14 @@ * 2) Makes sure that all buddies are in a group that exist. * 3) Deletes any empty groups * - * @param sess The oscar session. + * @param od The oscar odion. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_cleanlist(OscarSession *sess) +int aim_ssi_cleanlist(OscarData *od) { struct aim_ssi_item *cur, *next; - if (!sess) + if (!od) return -EINVAL; /* Delete any buddies, permits, or denies with empty names. */ @@ -666,27 +664,27 @@ /* DESTROY any buddies that are directly in the master group. */ /* Do the same for buddies that are in a non-existant group. */ /* This will kind of mess up if you hit the item limit, but this function isn't too critical */ - cur = sess->ssi.local; + cur = od->ssi.local; while (cur) { next = cur->next; if (!cur->name) { if (cur->type == AIM_SSI_TYPE_BUDDY) - aim_ssi_delbuddy(sess, NULL, NULL); + aim_ssi_delbuddy(od, NULL, NULL); else if (cur->type == AIM_SSI_TYPE_PERMIT) - aim_ssi_delpermit(sess, NULL); + aim_ssi_delpermit(od, NULL); else if (cur->type == AIM_SSI_TYPE_DENY) - aim_ssi_deldeny(sess, NULL); - } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(sess->ssi.local, cur->gid, 0x0000)))) { - char *alias = aim_ssi_getalias(sess->ssi.local, NULL, cur->name); - aim_ssi_addbuddy(sess, cur->name, "orphans", alias, NULL, NULL, 0); - aim_ssi_delbuddy(sess, cur->name, NULL); + aim_ssi_deldeny(od, NULL); + } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(od->ssi.local, cur->gid, 0x0000)))) { + char *alias = aim_ssi_getalias(od->ssi.local, NULL, cur->name); + aim_ssi_addbuddy(od, cur->name, "orphans", alias, NULL, NULL, 0); + aim_ssi_delbuddy(od, cur->name, NULL); free(alias); } cur = next; } /* Make sure there aren't any duplicate buddies in a group, or duplicate permits or denies */ - cur = sess->ssi.local; + cur = od->ssi.local; while (cur) { if ((cur->type == AIM_SSI_TYPE_BUDDY) || (cur->type == AIM_SSI_TYPE_PERMIT) || (cur->type == AIM_SSI_TYPE_DENY)) { @@ -695,7 +693,7 @@ while (cur2) { next2 = cur2->next; if ((cur->type == cur2->type) && (cur->gid == cur2->gid) && (cur->name != NULL) && (cur2->name != NULL) && (!strcmp(cur->name, cur2->name))) { - aim_ssi_itemlist_del(&sess->ssi.local, cur2); + aim_ssi_itemlist_del(&od->ssi.local, cur2); } cur2 = next2; } @@ -704,23 +702,23 @@ } /* Check if there are empty groups and delete them */ - cur = sess->ssi.local; + cur = od->ssi.local; while (cur) { next = cur->next; if (cur->type == AIM_SSI_TYPE_GROUP) { aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c8, 1); if (!tlv || !tlv->length) - aim_ssi_itemlist_del(&sess->ssi.local, cur); + aim_ssi_itemlist_del(&od->ssi.local, cur); } cur = next; } /* Check if the master group is empty */ - if ((cur = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!cur->data)) - aim_ssi_itemlist_del(&sess->ssi.local, cur); + if ((cur = aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000)) && (!cur->data)) + aim_ssi_itemlist_del(&od->ssi.local, cur); /* If we've made any changes then sync our list with the server's */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -728,7 +726,7 @@ /** * Add a buddy to the list. * - * @param sess The oscar session. + * @param od The oscar odion. * @param name The name of the item. * @param group The group of the item. * @param alias The alias/nickname of the item, or NULL. @@ -736,26 +734,26 @@ * @param smsnum The locally assigned SMS number, or NULL. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_addbuddy(OscarSession *sess, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth) +int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth) { struct aim_ssi_item *parent; aim_tlvlist_t *data = NULL; - if (!sess || !name || !group) + if (!od || !name || !group) return -EINVAL; /* Find the parent */ - if (!(parent = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) { + if (!(parent = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) { /* Find the parent's parent (the master group) */ - if (!(parent = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000))) - if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) + if (!(parent = aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000))) + if (!(parent = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) return -ENOMEM; /* Add the parent */ - if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) + if (!(parent = aim_ssi_itemlist_add(&od->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) return -ENOMEM; /* Modify the parent's parent (the master group) */ - aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL); + aim_ssi_itemlist_rebuildgroup(od->ssi.local, NULL); } /* Create a TLV list for the new buddy */ @@ -769,14 +767,14 @@ aim_tlvlist_add_str(&data, 0x013c, comment); /* Add that bad boy */ - aim_ssi_itemlist_add(&sess->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data); + aim_ssi_itemlist_add(&od->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data); aim_tlvlist_free(&data); /* Modify the parent group */ - aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group); + aim_ssi_itemlist_rebuildgroup(od->ssi.local, group); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -784,21 +782,21 @@ /** * Add a permit buddy to the list. * - * @param sess The oscar session. + * @param od The oscar odion. * @param name The name of the item.. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_addpermit(OscarSession *sess, const char *name) +int aim_ssi_addpermit(OscarData *od, const char *name) { - if (!sess || !name) + if (!od || !name) return -EINVAL; /* Add that bad boy */ - aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_PERMIT, NULL); + aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_PERMIT, NULL); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -806,21 +804,21 @@ /** * Add a deny buddy to the list. * - * @param sess The oscar session. + * @param od The oscar odion. * @param name The name of the item.. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_adddeny(OscarSession *sess, const char *name) +int aim_ssi_adddeny(OscarData *od, const char *name) { - if (!sess || !name) + if (!od || !name) return -EINVAL; /* Add that bad boy */ - aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_DENY, NULL); + aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_DENY, NULL); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -828,43 +826,43 @@ /** * Deletes a buddy from the list. * - * @param sess The oscar session. + * @param od The oscar odion. * @param name The name of the item, or NULL. * @param group The group of the item, or NULL. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_delbuddy(OscarSession *sess, const char *name, const char *group) +int aim_ssi_delbuddy(OscarData *od, const char *name, const char *group) { struct aim_ssi_item *del; - if (!sess) + if (!od) return -EINVAL; /* Find the buddy */ - if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, group, name, AIM_SSI_TYPE_BUDDY))) + if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, name, AIM_SSI_TYPE_BUDDY))) return -EINVAL; /* Remove the item from the list */ - aim_ssi_itemlist_del(&sess->ssi.local, del); + aim_ssi_itemlist_del(&od->ssi.local, del); /* Modify the parent group */ - aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group); + aim_ssi_itemlist_rebuildgroup(od->ssi.local, group); /* Check if we should delete the parent group */ - if ((del = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)) && (!del->data)) { - aim_ssi_itemlist_del(&sess->ssi.local, del); + if ((del = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)) && (!del->data)) { + aim_ssi_itemlist_del(&od->ssi.local, del); /* Modify the parent group */ - aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL); + aim_ssi_itemlist_rebuildgroup(od->ssi.local, NULL); /* Check if we should delete the parent's parent (the master group) */ - if ((del = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!del->data)) { - aim_ssi_itemlist_del(&sess->ssi.local, del); + if ((del = aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000)) && (!del->data)) { + aim_ssi_itemlist_del(&od->ssi.local, del); } } /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -872,26 +870,26 @@ /** * Deletes a permit buddy from the list. * - * @param sess The oscar session. + * @param od The oscar odion. * @param name The name of the item, or NULL. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_delpermit(OscarSession *sess, const char *name) +int aim_ssi_delpermit(OscarData *od, const char *name) { struct aim_ssi_item *del; - if (!sess) + if (!od) return -EINVAL; /* Find the item */ - if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_PERMIT))) + if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, NULL, name, AIM_SSI_TYPE_PERMIT))) return -EINVAL; /* Remove the item from the list */ - aim_ssi_itemlist_del(&sess->ssi.local, del); + aim_ssi_itemlist_del(&od->ssi.local, del); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -899,26 +897,26 @@ /** * Deletes a deny buddy from the list. * - * @param sess The oscar session. + * @param od The oscar odion. * @param name The name of the item, or NULL. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_deldeny(OscarSession *sess, const char *name) +int aim_ssi_deldeny(OscarData *od, const char *name) { struct aim_ssi_item *del; - if (!sess) + if (!od) return -EINVAL; /* Find the item */ - if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_DENY))) + if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, NULL, name, AIM_SSI_TYPE_DENY))) return -EINVAL; /* Remove the item from the list */ - aim_ssi_itemlist_del(&sess->ssi.local, del); + aim_ssi_itemlist_del(&od->ssi.local, del); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -927,17 +925,17 @@ * Move a buddy from one group to another group. This basically just deletes the * buddy and re-adds it. * - * @param sess The oscar session. + * @param od The oscar odion. * @param oldgn The group that the buddy is currently in. * @param newgn The group that the buddy should be moved in to. * @param sn The name of the buddy to be moved. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_movebuddy(OscarSession *sess, const char *oldgn, const char *newgn, const char *sn) +int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *sn) { - char *alias = aim_ssi_getalias(sess->ssi.local, oldgn, sn); - aim_ssi_addbuddy(sess, sn, newgn, alias, NULL, NULL, aim_ssi_waitingforauth(sess->ssi.local, oldgn, sn)); - aim_ssi_delbuddy(sess, sn, oldgn); + char *alias = aim_ssi_getalias(od->ssi.local, oldgn, sn); + aim_ssi_addbuddy(od, sn, newgn, alias, NULL, NULL, aim_ssi_waitingforauth(od->ssi.local, oldgn, sn)); + aim_ssi_delbuddy(od, sn, oldgn); free(alias); return 0; } @@ -945,21 +943,21 @@ /** * Change the alias stored on the server for a given buddy. * - * @param sess The oscar session. + * @param od The oscar odion. * @param gn The group that the buddy is currently in. * @param sn The screen name of the buddy. * @param alias The new alias for the buddy, or NULL if you want to remove * a buddy's comment. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_aliasbuddy(OscarSession *sess, const char *gn, const char *sn, const char *alias) +int aim_ssi_aliasbuddy(OscarData *od, const char *gn, const char *sn, const char *alias) { struct aim_ssi_item *tmp; - if (!sess || !gn || !sn) + if (!od || !gn || !sn) return -EINVAL; - if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY))) + if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY))) return -EINVAL; /* Either add or remove the 0x0131 TLV from the TLV chain */ @@ -969,7 +967,7 @@ aim_tlvlist_remove(&tmp->data, 0x0131); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -977,21 +975,21 @@ /** * Change the comment stored on the server for a given buddy. * - * @param sess The oscar session. + * @param od The oscar odion. * @param gn The group that the buddy is currently in. * @param sn The screen name of the buddy. * @param alias The new comment for the buddy, or NULL if you want to remove * a buddy's comment. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_editcomment(OscarSession *sess, const char *gn, const char *sn, const char *comment) +int aim_ssi_editcomment(OscarData *od, const char *gn, const char *sn, const char *comment) { struct aim_ssi_item *tmp; - if (!sess || !gn || !sn) + if (!od || !gn || !sn) return -EINVAL; - if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY))) + if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY))) return -EINVAL; /* Either add or remove the 0x0131 TLV from the TLV chain */ @@ -1001,7 +999,7 @@ aim_tlvlist_remove(&tmp->data, 0x013c); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -1009,19 +1007,19 @@ /** * Rename a group. * - * @param sess The oscar session. + * @param od The oscar odion. * @param oldgn The old group name. * @param newgn The new group name. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_rename_group(OscarSession *sess, const char *oldgn, const char *newgn) +int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn) { struct aim_ssi_item *group; - if (!sess || !oldgn || !newgn) + if (!od || !oldgn || !newgn) return -EINVAL; - if (!(group = aim_ssi_itemlist_finditem(sess->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP))) + if (!(group = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP))) return -EINVAL; free(group->name); @@ -1029,7 +1027,7 @@ strcpy(group->name, newgn); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -1037,7 +1035,7 @@ /** * Stores your permit/deny setting on the server, and starts using it. * - * @param sess The oscar session. + * @param od The oscar odion. * @param permdeny Your permit/deny setting. Can be one of the following: * 1 - Allow all users * 2 - Block all users @@ -1048,16 +1046,16 @@ * visible. See the AIM_FLAG_BLEH #defines in oscar.h * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_setpermdeny(OscarSession *sess, guint8 permdeny, guint32 vismask) +int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny, guint32 vismask) { struct aim_ssi_item *tmp; - if (!sess) + if (!od) return -EINVAL; /* Find the PDINFO item, or add it if it does not exist */ - if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) - tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL); + if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) + tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL); /* Need to add the 0x00ca TLV to the TLV chain */ aim_tlvlist_replace_8(&tmp->data, 0x00ca, permdeny); @@ -1066,7 +1064,7 @@ aim_tlvlist_replace_32(&tmp->data, 0x00cb, vismask); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -1074,27 +1072,26 @@ /** * Set buddy icon information * - * @param sess The oscar session. + * @param od The oscar odion. * @param iconcsum The MD5 checksum of the icon you are using. * @param iconcsumlen Length of the MD5 checksum given above. Should be 0x10 bytes. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_seticon(OscarSession *sess, guint8 *iconsum, guint16 iconsumlen) +int aim_ssi_seticon(OscarData *od, guint8 *iconsum, guint16 iconsumlen) { struct aim_ssi_item *tmp; guint8 *csumdata; - if (!sess || !iconsum || !iconsumlen) + if (!od || !iconsum || !iconsumlen) return -EINVAL; /* Find the ICONINFO item, or add it if it does not exist */ - if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) { - tmp = aim_ssi_itemlist_add(&sess->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, NULL); + if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) { + tmp = aim_ssi_itemlist_add(&od->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, NULL); } /* Need to add the 0x00d5 TLV to the TLV chain */ - if (!(csumdata = (guint8 *)malloc((iconsumlen+2)*sizeof(guint8)))) - return -ENOMEM; + csumdata = (guint8 *)malloc((iconsumlen+2)*sizeof(guint8)); csumdata[0] = 0x00; csumdata[1] = 0x10; memcpy(&csumdata[2], iconsum, iconsumlen); @@ -1105,30 +1102,30 @@ aim_tlvlist_replace_noval(&tmp->data, 0x0131); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } /** - * Remove a reference to a server stored buddy icon. This will make your + * Remove a reference to a server stored buddy icon. This will make your * icon stop showing up to other people. * - * @param sess The oscar session. + * @param od The oscar odion. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_delicon(OscarSession *sess) +int aim_ssi_delicon(OscarData *od) { struct aim_ssi_item *tmp; - if (!sess) + if (!od) return -EINVAL; /* Find the ICONINFO item and delete it if it exists*/ - if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) - aim_ssi_itemlist_del(&sess->ssi.local, tmp); + if ((tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) + aim_ssi_itemlist_del(&od->ssi.local, tmp); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -1136,27 +1133,27 @@ * Stores your setting for various SSI settings. Whether you * should show up as idle or not, etc. * - * @param sess The oscar session. + * @param od The oscar odion. * @param presence I think it's a bitmask, but I only know what one of the bits is: * 0x00000002 - Hide wireless? * 0x00000400 - Allow others to see your idle time * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_ssi_setpresence(OscarSession *sess, guint32 presence) { +int aim_ssi_setpresence(OscarData *od, guint32 presence) { struct aim_ssi_item *tmp; - if (!sess) + if (!od) return -EINVAL; /* Find the PRESENCEPREFS item, or add it if it does not exist */ - if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) - tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL); + if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) + tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL); /* Need to add the x00c9 TLV to the TLV chain */ aim_tlvlist_replace_32(&tmp->data, 0x00c9, presence); /* Sync our local list with the server list */ - aim_ssi_sync(sess); + aim_ssi_sync(od); return 0; } @@ -1164,20 +1161,20 @@ /* * Subtype 0x0002 - Request SSI Rights. */ -faim_export int aim_ssi_reqrights(OscarSession *sess) +int aim_ssi_reqrights(OscarData *od) { - OscarConnection *conn; + FlapConnection *conn; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; - return aim_genericreq_n_snacid(sess, conn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_REQRIGHTS); + return aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQRIGHTS); } /* * Subtype 0x0003 - SSI Rights Information. */ -static int parserights(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int parserights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0, i; aim_rxcallback_t userfunc; @@ -1195,18 +1192,15 @@ return 0; } - aim_bstream_init(&bstream, tlv->value, tlv->length); + byte_stream_init(&bstream, tlv->value, tlv->length); - if (!(maxitems = (guint16 *)malloc((tlv->length/2)*sizeof(guint16)))) { - aim_tlvlist_free(&tlvlist); - return 0; - } + maxitems = (guint16 *)malloc((tlv->length/2)*sizeof(guint16)); for (i=0; i<(tlv->length/2); i++) - maxitems[i] = aimbs_get16(&bstream); + maxitems[i] = byte_stream_get16(&bstream); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, tlv->length/2, maxitems); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, tlv->length/2, maxitems); aim_tlvlist_free(&tlvlist); free(maxitems); @@ -1215,55 +1209,54 @@ } /* - * Subtype 0x0004 - Request SSI Data when you don't have a timestamp and + * Subtype 0x0004 - Request SSI Data when you don't have a timestamp and * revision number. - * + * */ -faim_export int aim_ssi_reqdata(OscarSession *sess) +int aim_ssi_reqdata(OscarData *od) { - OscarConnection *conn; + FlapConnection *conn; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; /* Free any current data, just in case */ - aim_ssi_freelist(sess); + aim_ssi_freelist(od); - return aim_genericreq_n_snacid(sess, conn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_REQDATA); + return aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQDATA); } /* - * Subtype 0x0005 - Request SSI Data when you have a timestamp and revision + * Subtype 0x0005 - Request SSI Data when you have a timestamp and revision * number. * * The data will only be sent if it is newer than the posted local * timestamp and revision. - * + * * Note that the client should never increment the revision, only the server. - * + * */ -faim_export int aim_ssi_reqifchanged(OscarSession *sess, time_t timestamp, guint16 numitems) +int aim_ssi_reqifchanged(OscarData *od, time_t timestamp, guint16 numitems) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+4+2); - snacid = aim_cachesnac(sess, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_REQIFCHANGED, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQIFCHANGED, 0x0000, NULL, 0); - aim_putsnac(&fr->data, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_REQIFCHANGED, 0x0000, snacid); - aimbs_put32(&fr->data, timestamp); - aimbs_put16(&fr->data, numitems); + aim_putsnac(&frame->data, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQIFCHANGED, 0x0000, snacid); + byte_stream_put32(&frame->data, timestamp); + byte_stream_put16(&frame->data, numitems); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); /* Free any current data, just in case */ - aim_ssi_freelist(sess); + aim_ssi_freelist(od); return 0; } @@ -1271,7 +1264,7 @@ /* * Subtype 0x0006 - SSI Data. */ -static int parsedata(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int parsedata(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1280,37 +1273,37 @@ char *name; aim_tlvlist_t *data; - fmtver = aimbs_get8(bs); /* Version of ssi data. Should be 0x00 */ - sess->ssi.numitems += aimbs_get16(bs); /* # of items in this SSI SNAC */ + fmtver = byte_stream_get8(bs); /* Version of ssi data. Should be 0x00 */ + od->ssi.numitems += byte_stream_get16(bs); /* # of items in this SSI SNAC */ /* Read in the list */ - while (aim_bstream_empty(bs) > 4) { /* last four bytes are timestamp */ - if ((namelen = aimbs_get16(bs))) - name = aimbs_getstr(bs, namelen); + while (byte_stream_empty(bs) > 4) { /* last four bytes are timestamp */ + if ((namelen = byte_stream_get16(bs))) + name = byte_stream_getstr(bs, namelen); else name = NULL; - gid = aimbs_get16(bs); - bid = aimbs_get16(bs); - type = aimbs_get16(bs); - data = aim_tlvlist_readlen(bs, aimbs_get16(bs)); - aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data); + gid = byte_stream_get16(bs); + bid = byte_stream_get16(bs); + type = byte_stream_get16(bs); + data = aim_tlvlist_readlen(bs, byte_stream_get16(bs)); + aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data); free(name); aim_tlvlist_free(&data); } /* Read in the timestamp */ - sess->ssi.timestamp = aimbs_get32(bs); + od->ssi.timestamp = byte_stream_get32(bs); if (!(snac->flags & 0x0001)) { /* Make a copy of the list */ struct aim_ssi_item *cur; - for (cur=sess->ssi.official; cur; cur=cur->next) - aim_ssi_itemlist_add(&sess->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data); + for (cur=od->ssi.official; cur; cur=cur->next) + aim_ssi_itemlist_add(&od->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data); - sess->ssi.received_data = 1; + od->ssi.received_data = 1; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, fmtver, sess->ssi.numitems, sess->ssi.official, sess->ssi.timestamp); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, fmtver, od->ssi.numitems, od->ssi.official, od->ssi.timestamp); } return ret; @@ -1325,14 +1318,14 @@ * settings into effect. * */ -faim_export int aim_ssi_enable(OscarSession *sess) +int aim_ssi_enable(OscarData *od) { - OscarConnection *conn; + FlapConnection *conn; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; - return aim_genericreq_n(sess, conn, OSCAR_FAMILY_FEEDBAG, 0x0007); + return aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, 0x0007); } /* @@ -1343,20 +1336,20 @@ * difference is the subtype that is set for the SNAC. * */ -faim_export int aim_ssi_addmoddel(OscarSession *sess) +int aim_ssi_addmoddel(OscarData *od) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int snaclen; struct aim_ssi_tmp *cur; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG)) || !sess->ssi.pending || !sess->ssi.pending->item) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !od->ssi.pending || !od->ssi.pending->item) return -EINVAL; /* Calculate total SNAC size */ snaclen = 10; /* For family, subtype, flags, and SNAC ID */ - for (cur=sess->ssi.pending; cur; cur=cur->next) { + for (cur=od->ssi.pending; cur; cur=cur->next) { snaclen += 10; /* For length, GID, BID, type, and length */ if (cur->item->name) snaclen += strlen(cur->item->name); @@ -1364,25 +1357,24 @@ snaclen += aim_tlvlist_size(&cur->item->data); } - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, snaclen); - snacid = aim_cachesnac(sess, OSCAR_FAMILY_FEEDBAG, sess->ssi.pending->action, 0x0000, NULL, 0); - aim_putsnac(&fr->data, OSCAR_FAMILY_FEEDBAG, sess->ssi.pending->action, 0x0000, snacid); + snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, od->ssi.pending->action, 0x0000, NULL, 0); + aim_putsnac(&frame->data, SNAC_FAMILY_FEEDBAG, od->ssi.pending->action, 0x0000, snacid); - for (cur=sess->ssi.pending; cur; cur=cur->next) { - aimbs_put16(&fr->data, cur->item->name ? strlen(cur->item->name) : 0); + for (cur=od->ssi.pending; cur; cur=cur->next) { + byte_stream_put16(&frame->data, cur->item->name ? strlen(cur->item->name) : 0); if (cur->item->name) - aimbs_putstr(&fr->data, cur->item->name); - aimbs_put16(&fr->data, cur->item->gid); - aimbs_put16(&fr->data, cur->item->bid); - aimbs_put16(&fr->data, cur->item->type); - aimbs_put16(&fr->data, cur->item->data ? aim_tlvlist_size(&cur->item->data) : 0); + byte_stream_putstr(&frame->data, cur->item->name); + byte_stream_put16(&frame->data, cur->item->gid); + byte_stream_put16(&frame->data, cur->item->bid); + byte_stream_put16(&frame->data, cur->item->type); + byte_stream_put16(&frame->data, cur->item->data ? aim_tlvlist_size(&cur->item->data) : 0); if (cur->item->data) - aim_tlvlist_write(&fr->data, &cur->item->data); + aim_tlvlist_write(&frame->data, &cur->item->data); } - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1393,7 +1385,7 @@ * Sent by the server, for example, when someone is added to * your "Recent Buddies" group. */ -static int parseadd(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int parseadd(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1401,25 +1393,25 @@ guint16 len, gid, bid, type; aim_tlvlist_t *data; - while (aim_bstream_empty(bs)) { - if ((len = aimbs_get16(bs))) - name = aimbs_getstr(bs, len); + while (byte_stream_empty(bs)) { + if ((len = byte_stream_get16(bs))) + name = byte_stream_getstr(bs, len); else name = NULL; - gid = aimbs_get16(bs); - bid = aimbs_get16(bs); - type = aimbs_get16(bs); - if ((len = aimbs_get16(bs))) + gid = byte_stream_get16(bs); + bid = byte_stream_get16(bs); + type = byte_stream_get16(bs); + if ((len = byte_stream_get16(bs))) data = aim_tlvlist_readlen(bs, len); else data = NULL; - aim_ssi_itemlist_add(&sess->ssi.local, name, gid, bid, type, data); - aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data); + aim_ssi_itemlist_add(&od->ssi.local, name, gid, bid, type, data); + aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data); aim_tlvlist_free(&data); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, type, name); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, type, name); free(name); } @@ -1432,7 +1424,7 @@ * * XXX - It would probably be good for the client to actually do something when it gets this. */ -static int parsemod(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int parsemod(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1441,21 +1433,21 @@ aim_tlvlist_t *data; struct aim_ssi_item *item; - while (aim_bstream_empty(bs)) { - if ((len = aimbs_get16(bs))) - name = aimbs_getstr(bs, len); + while (byte_stream_empty(bs)) { + if ((len = byte_stream_get16(bs))) + name = byte_stream_getstr(bs, len); else name = NULL; - gid = aimbs_get16(bs); - bid = aimbs_get16(bs); - type = aimbs_get16(bs); - if ((len = aimbs_get16(bs))) + gid = byte_stream_get16(bs); + bid = byte_stream_get16(bs); + type = byte_stream_get16(bs); + if ((len = byte_stream_get16(bs))) data = aim_tlvlist_readlen(bs, len); else data = NULL; /* Replace the 2 local items with the given one */ - if ((item = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) { + if ((item = aim_ssi_itemlist_find(od->ssi.local, gid, bid))) { item->type = type; free(item->name); if (name) { @@ -1467,7 +1459,7 @@ item->data = aim_tlvlist_copy(data); } - if ((item = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) { + if ((item = aim_ssi_itemlist_find(od->ssi.official, gid, bid))) { item->type = type; free(item->name); if (name) { @@ -1479,8 +1471,8 @@ item->data = aim_tlvlist_copy(data); } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame); free(name); aim_tlvlist_free(&data); @@ -1494,27 +1486,27 @@ * * XXX - It would probably be good for the client to actually do something when it gets this. */ -static int parsedel(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int parsedel(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; guint16 gid, bid; struct aim_ssi_item *del; - while (aim_bstream_empty(bs)) { - aim_bstream_advance(bs, aimbs_get16(bs)); - gid = aimbs_get16(bs); - bid = aimbs_get16(bs); - aimbs_get16(bs); - aim_bstream_advance(bs, aimbs_get16(bs)); + while (byte_stream_empty(bs)) { + byte_stream_advance(bs, byte_stream_get16(bs)); + gid = byte_stream_get16(bs); + bid = byte_stream_get16(bs); + byte_stream_get16(bs); + byte_stream_advance(bs, byte_stream_get16(bs)); - if ((del = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) - aim_ssi_itemlist_del(&sess->ssi.local, del); - if ((del = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) - aim_ssi_itemlist_del(&sess->ssi.official, del); + if ((del = aim_ssi_itemlist_find(od->ssi.local, gid, bid))) + aim_ssi_itemlist_del(&od->ssi.local, del); + if ((del = aim_ssi_itemlist_find(od->ssi.official, gid, bid))) + aim_ssi_itemlist_del(&od->ssi.official, del); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame); } return ret; @@ -1526,45 +1518,45 @@ * Response to add, modify, or delete SNAC (sent with aim_ssi_addmoddel). * */ -static int parseack(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int parseack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; struct aim_ssi_tmp *cur, *del; /* Read in the success/failure flags from the ack SNAC */ - cur = sess->ssi.pending; - while (cur && (aim_bstream_empty(bs)>0)) { - cur->ack = aimbs_get16(bs); + cur = od->ssi.pending; + while (cur && (byte_stream_empty(bs)>0)) { + cur->ack = byte_stream_get16(bs); cur = cur->next; } /* - * If outcome is 0, then add the item to the item list, or replace the other item, - * or remove the old item. If outcome is non-zero, then remove the item from the + * If outcome is 0, then add the item to the item list, or replace the other item, + * or remove the old item. If outcome is non-zero, then remove the item from the * local list, or unmodify it, or add it. */ - for (cur=sess->ssi.pending; (cur && (cur->ack != 0xffff)); cur=cur->next) { + for (cur=od->ssi.pending; (cur && (cur->ack != 0xffff)); cur=cur->next) { if (cur->item) { if (cur->ack) { /* Our action was unsuccessful, so change the local list back to how it was */ - if (cur->action == OSCAR_SUBTYPE_FEEDBAG_ADD) { + if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) { /* Remove the item from the local list */ /* Make sure cur->item is still valid memory */ - if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { + if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) { if (cur->item->name) { cur->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char)); strcpy(cur->name, cur->item->name); } - aim_ssi_itemlist_del(&sess->ssi.local, cur->item); + aim_ssi_itemlist_del(&od->ssi.local, cur->item); } cur->item = NULL; - } else if (cur->action == OSCAR_SUBTYPE_FEEDBAG_MOD) { + } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) { /* Replace the local item with the item from the official list */ - if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { + if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) { struct aim_ssi_item *cur1; - if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) { + if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) { free(cur->item->name); if (cur1->name) { cur->item->name = (char *)malloc((strlen(cur1->name)+1)*sizeof(char)); @@ -1577,28 +1569,28 @@ } else cur->item = NULL; - } else if (cur->action == OSCAR_SUBTYPE_FEEDBAG_DEL) { + } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) { /* Add the item back into the local list */ - if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item)) { - aim_ssi_itemlist_add(&sess->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); + if (aim_ssi_itemlist_valid(od->ssi.official, cur->item)) { + aim_ssi_itemlist_add(&od->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); } else cur->item = NULL; } } else { /* Do the exact opposite */ - if (cur->action == OSCAR_SUBTYPE_FEEDBAG_ADD) { + if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) { /* Add the local item to the official list */ - if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { - aim_ssi_itemlist_add(&sess->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); + if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) { + aim_ssi_itemlist_add(&od->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); } else cur->item = NULL; - } else if (cur->action == OSCAR_SUBTYPE_FEEDBAG_MOD) { + } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) { /* Replace the official item with the item from the local list */ - if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { + if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) { struct aim_ssi_item *cur1; - if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) { + if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) { free(cur1->name); if (cur->item->name) { cur1->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char)); @@ -1611,10 +1603,10 @@ } else cur->item = NULL; - } else if (cur->action == OSCAR_SUBTYPE_FEEDBAG_DEL) { + } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) { /* Remove the item from the official list */ - if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item)) - aim_ssi_itemlist_del(&sess->ssi.official, cur->item); + if (aim_ssi_itemlist_valid(od->ssi.official, cur->item)) + aim_ssi_itemlist_del(&od->ssi.official, cur->item); cur->item = NULL; } @@ -1622,24 +1614,24 @@ } /* End if (cur->item) */ } /* End for loop */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, sess->ssi.pending); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, od->ssi.pending); /* Free all aim_ssi_tmp's with an outcome */ - cur = sess->ssi.pending; + cur = od->ssi.pending; while (cur && (cur->ack != 0xffff)) { del = cur; cur = cur->next; free(del->name); free(del); } - sess->ssi.pending = cur; + od->ssi.pending = cur; /* If we're not waiting for any more acks, then send more SNACs */ - if (!sess->ssi.pending) { - sess->ssi.pending = NULL; - sess->ssi.waiting_for_ack = 0; - aim_ssi_sync(sess); + if (!od->ssi.pending) { + od->ssi.pending = NULL; + od->ssi.waiting_for_ack = 0; + aim_ssi_sync(od); } return ret; @@ -1652,15 +1644,15 @@ * posted local stamp/revision. * */ -static int parsedataunchanged(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int parsedataunchanged(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; - sess->ssi.received_data = 1; + od->ssi.received_data = 1; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame); return ret; } @@ -1668,33 +1660,32 @@ /* * Subtype 0x0011 - SSI Begin Data Modification. * - * Tells the server you're going to start modifying data. - * + * Tell the server you're going to start modifying data. */ -faim_export int aim_ssi_modbegin(OscarSession *sess) +int aim_ssi_modbegin(OscarData *od) { - OscarConnection *conn; + FlapConnection *conn; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; - return aim_genericreq_n(sess, conn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_EDITSTART); + return aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_EDITSTART); } /* * Subtype 0x0012 - SSI End Data Modification. * - * Tells the server you're finished modifying data. + * Tell the server you're finished modifying data. * */ -faim_export int aim_ssi_modend(OscarSession *sess) +int aim_ssi_modend(OscarData *od) { - OscarConnection *conn; + FlapConnection *conn; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) return -EINVAL; - return aim_genericreq_n(sess, conn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_EDITSTOP); + return aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_EDITSTOP); } /* @@ -1703,36 +1694,35 @@ * Authorizes a contact so they can add you to their contact list. * */ -faim_export int aim_ssi_sendauth(OscarSession *sess, char *sn, char *msg) +int aim_ssi_sendauth(OscarData *od, char *sn, char *msg) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG)) || !sn) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !sn) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2); - snacid = aim_cachesnac(sess, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_SENDAUTH, 0x0000, NULL, 0); - aim_putsnac(&fr->data, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_SENDAUTH, 0x0000, snacid); + snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTH, 0x0000, NULL, 0); + aim_putsnac(&frame->data, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTH, 0x0000, snacid); /* Screen name */ - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); /* Message (null terminated) */ - aimbs_put16(&fr->data, msg ? strlen(msg) : 0); + byte_stream_put16(&frame->data, msg ? strlen(msg) : 0); if (msg) { - aimbs_putstr(&fr->data, msg); - aimbs_put8(&fr->data, 0x00); + byte_stream_putstr(&frame->data, msg); + byte_stream_put8(&frame->data, 0x00); } /* Unknown */ - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1740,7 +1730,7 @@ /* * Subtype 0x0015 - Receive an authorization grant */ -static int receiveauthgrant(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int receiveauthgrant(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1748,22 +1738,22 @@ char *sn, *msg; /* Read screen name */ - if ((tmp = aimbs_get8(bs))) - sn = aimbs_getstr(bs, tmp); + if ((tmp = byte_stream_get8(bs))) + sn = byte_stream_getstr(bs, tmp); else sn = NULL; /* Read message (null terminated) */ - if ((tmp = aimbs_get16(bs))) - msg = aimbs_getstr(bs, tmp); + if ((tmp = byte_stream_get16(bs))) + msg = byte_stream_getstr(bs, tmp); else msg = NULL; /* Unknown */ - tmp = aimbs_get16(bs); + tmp = byte_stream_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, sn, msg); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, sn, msg); free(sn); free(msg); @@ -1778,36 +1768,35 @@ * granted, denied, or dropped. * */ -faim_export int aim_ssi_sendauthrequest(OscarSession *sess, char *sn, const char *msg) +int aim_ssi_sendauthrequest(OscarData *od, char *sn, const char *msg) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG)) || !sn) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !sn) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2); - snacid = aim_cachesnac(sess, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_SENDAUTHREQ, 0x0000, NULL, 0); - aim_putsnac(&fr->data, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_SENDAUTHREQ, 0x0000, snacid); + snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREQ, 0x0000, NULL, 0); + aim_putsnac(&frame->data, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREQ, 0x0000, snacid); /* Screen name */ - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); /* Message (null terminated) */ - aimbs_put16(&fr->data, msg ? strlen(msg) : 0); + byte_stream_put16(&frame->data, msg ? strlen(msg) : 0); if (msg) { - aimbs_putstr(&fr->data, msg); - aimbs_put8(&fr->data, 0x00); + byte_stream_putstr(&frame->data, msg); + byte_stream_put8(&frame->data, 0x00); } /* Unknown */ - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1815,7 +1804,7 @@ /* * Subtype 0x0019 - Receive an authorization request */ -static int receiveauthrequest(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int receiveauthrequest(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1823,22 +1812,22 @@ char *sn, *msg; /* Read screen name */ - if ((tmp = aimbs_get8(bs))) - sn = aimbs_getstr(bs, tmp); + if ((tmp = byte_stream_get8(bs))) + sn = byte_stream_getstr(bs, tmp); else sn = NULL; /* Read message (null terminated) */ - if ((tmp = aimbs_get16(bs))) - msg = aimbs_getstr(bs, tmp); + if ((tmp = byte_stream_get16(bs))) + msg = byte_stream_getstr(bs, tmp); else msg = NULL; /* Unknown */ - tmp = aimbs_get16(bs); + tmp = byte_stream_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, sn, msg); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, sn, msg); free(sn); free(msg); @@ -1856,39 +1845,38 @@ * if reply=0x01 then grant * */ -faim_export int aim_ssi_sendauthreply(OscarSession *sess, char *sn, guint8 reply, const char *msg) +int aim_ssi_sendauthreply(OscarData *od, char *sn, guint8 reply, const char *msg) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_FEEDBAG)) || !sn) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !sn) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 1 + 2+(msg ? strlen(msg)+1 : 0) + 2))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 1+strlen(sn) + 1 + 2+(msg ? strlen(msg)+1 : 0) + 2); - snacid = aim_cachesnac(sess, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_SENDAUTHREP, 0x0000, NULL, 0); - aim_putsnac(&fr->data, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_SENDAUTHREP, 0x0000, snacid); + snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP, 0x0000, NULL, 0); + aim_putsnac(&frame->data, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP, 0x0000, snacid); /* Screen name */ - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); /* Grant or deny */ - aimbs_put8(&fr->data, reply); + byte_stream_put8(&frame->data, reply); /* Message (null terminated) */ - aimbs_put16(&fr->data, msg ? (strlen(msg)+1) : 0); + byte_stream_put16(&frame->data, msg ? (strlen(msg)+1) : 0); if (msg) { - aimbs_putstr(&fr->data, msg); - aimbs_put8(&fr->data, 0x00); + byte_stream_putstr(&frame->data, msg); + byte_stream_put8(&frame->data, 0x00); } /* Unknown */ - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1898,7 +1886,7 @@ * You get this bad boy when other people respond to the authorization * request that you have previously sent them. */ -static int receiveauthreply(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int receiveauthreply(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1907,25 +1895,25 @@ char *sn, *msg; /* Read screen name */ - if ((tmp = aimbs_get8(bs))) - sn = aimbs_getstr(bs, tmp); + if ((tmp = byte_stream_get8(bs))) + sn = byte_stream_getstr(bs, tmp); else sn = NULL; /* Read reply */ - reply = aimbs_get8(bs); + reply = byte_stream_get8(bs); /* Read message (null terminated) */ - if ((tmp = aimbs_get16(bs))) - msg = aimbs_getstr(bs, tmp); + if ((tmp = byte_stream_get16(bs))) + msg = byte_stream_getstr(bs, tmp); else msg = NULL; /* Unknown */ - tmp = aimbs_get16(bs); + tmp = byte_stream_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, sn, reply, msg); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, sn, reply, msg); free(sn); free(msg); @@ -1936,7 +1924,7 @@ /* * Subtype 0x001c - Receive a message telling you someone added you to their list. */ -static int receiveadded(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int receiveadded(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1944,57 +1932,58 @@ char *sn; /* Read screen name */ - if ((tmp = aimbs_get8(bs))) - sn = aimbs_getstr(bs, tmp); + if ((tmp = byte_stream_get8(bs))) + sn = byte_stream_getstr(bs, tmp); else sn = NULL; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, sn); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, sn); free(sn); return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - - if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_RIGHTSINFO) - return parserights(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_LIST) - return parsedata(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_ADD) - return parseadd(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_MOD) - return parsemod(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_DEL) - return parsedel(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_SRVACK) - return parseack(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_NOLIST) - return parsedataunchanged(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_RECVAUTH) - return receiveauthgrant(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_RECVAUTHREQ) - return receiveauthrequest(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_RECVAUTHREP) - return receiveauthreply(sess, mod, rx, snac, bs); - else if (snac->subtype == OSCAR_SUBTYPE_FEEDBAG_ADDED) - return receiveadded(sess, mod, rx, snac, bs); + if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO) + return parserights(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_LIST) + return parsedata(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_ADD) + return parseadd(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_MOD) + return parsemod(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_DEL) + return parsedel(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_SRVACK) + return parseack(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_NOLIST) + return parsedataunchanged(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RECVAUTH) + return receiveauthgrant(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ) + return receiveauthrequest(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP) + return receiveauthreply(od, conn, mod, frame, snac, bs); + else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_ADDED) + return receiveadded(od, conn, mod, frame, snac, bs); return 0; } -static void ssi_shutdown(OscarSession *sess, aim_module_t *mod) +static void +ssi_shutdown(OscarData *od, aim_module_t *mod) { - aim_ssi_freelist(sess); + aim_ssi_freelist(od); } -faim_internal int ssi_modfirst(OscarSession *sess, aim_module_t *mod) +int +ssi_modfirst(OscarData *od, aim_module_t *mod) { - - mod->family = OSCAR_FAMILY_FEEDBAG; + mod->family = SNAC_FAMILY_FEEDBAG; mod->version = 0x0004; mod->toolid = 0x0110; mod->toolversion = 0x0629;
--- a/src/protocols/oscar/family_icbm.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_icbm.c Fri Apr 07 05:10:56 2006 +0000 @@ -41,9 +41,7 @@ * TODO: Split this up into an im.c file an an icbm.c file. It * will be beautiful, you'll see. * - * Need to rename all the mpmsg messages to aim_im_bleh. - * - * Make sure aim_conn_findbygroup is used by all functions. + * Make sure flap_connection_findbygroup is used by all functions. */ #include "oscar.h" @@ -65,19 +63,19 @@ */ static int aim_im_puticbm(ByteStream *bs, const guchar *c, guint16 channel, const char *sn) { - aimbs_putraw(bs, c, 8); - aimbs_put16(bs, channel); - aimbs_put8(bs, strlen(sn)); - aimbs_putstr(bs, sn); + byte_stream_putraw(bs, c, 8); + byte_stream_put16(bs, channel); + byte_stream_put8(bs, strlen(sn)); + byte_stream_putstr(bs, sn); return 8+2+1+strlen(sn); } -/* - * Extracted from aim_im_sendch2_sendfile_ask +/** * Generates a random ICBM cookie in a character array of length 8 * and copies it into the variable passed as cookie + * TODO: Maybe we should stop limiting our characters to the visible range? */ -faim_export void aim_icbm_makecookie(guchar *cookie) +void aim_icbm_makecookie(guchar *cookie) { int i; @@ -110,7 +108,7 @@ * the rest will always be the same. * */ -faim_export guint16 aim_im_fingerprint(const guint8 *msghdr, int len) +guint16 aim_im_fingerprint(const guint8 *msghdr, int len) { static const struct { guint16 clientid; @@ -157,35 +155,34 @@ * with the rather unreasonable defaults. * */ -faim_export int aim_im_setparams(OscarSession *sess, struct aim_icbmparameters *params) +int aim_im_setparams(OscarData *od, struct aim_icbmparameters *params) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; if (!params) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+16))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0002, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 10+16); + + snacid = aim_cachesnac(od, 0x0004, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0002, 0x0000, snacid); /* This is read-only (see Parameter Reply). Must be set to zero here. */ - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); /* These are all read-write */ - aimbs_put32(&fr->data, params->flags); - aimbs_put16(&fr->data, params->maxmsglen); - aimbs_put16(&fr->data, params->maxsenderwarn); - aimbs_put16(&fr->data, params->maxrecverwarn); - aimbs_put32(&fr->data, params->minmsginterval); - - aim_tx_enqueue(sess, fr); + byte_stream_put32(&frame->data, params->flags); + byte_stream_put16(&frame->data, params->maxmsglen); + byte_stream_put16(&frame->data, params->maxsenderwarn); + byte_stream_put16(&frame->data, params->maxrecverwarn); + byte_stream_put32(&frame->data, params->minmsginterval); + + flap_connection_send(conn, frame); return 0; } @@ -194,34 +191,34 @@ * Subtype 0x0004 - Request ICBM parameter information. * */ -faim_export int aim_im_reqparams(OscarSession *sess) +int aim_im_reqparams(OscarData *od) { - OscarConnection *conn; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + FlapConnection *conn; + + if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; - return aim_genericreq_n_snacid(sess, conn, 0x0004, 0x0004); + return aim_genericreq_n_snacid(od, conn, 0x0004, 0x0004); } /** * Subtype 0x0005 - Receive parameter information. * */ -static int aim_im_paraminfo(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int aim_im_paraminfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_rxcallback_t userfunc; struct aim_icbmparameters params; - params.maxchan = aimbs_get16(bs); - params.flags = aimbs_get32(bs); - params.maxmsglen = aimbs_get16(bs); - params.maxsenderwarn = aimbs_get16(bs); - params.maxrecverwarn = aimbs_get16(bs); - params.minmsginterval = aimbs_get32(bs); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx, ¶ms); + params.maxchan = byte_stream_get16(bs); + params.flags = byte_stream_get32(bs); + params.maxmsglen = byte_stream_get16(bs); + params.maxsenderwarn = byte_stream_get16(bs); + params.maxrecverwarn = byte_stream_get16(bs); + params.minmsginterval = byte_stream_get32(bs); + + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + return userfunc(od, conn, frame, ¶ms); return 0; } @@ -267,16 +264,16 @@ * XXX - check SNAC size for multipart * */ -faim_export int aim_im_sendch1_ext(OscarSession *sess, struct aim_sendimext_args *args) +int aim_im_sendch1_ext(OscarData *od, struct aim_sendimext_args *args) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; guchar cookie[8]; int msgtlvlen; static const guint8 deffeatures[] = { 0x01, 0x01, 0x01, 0x02 }; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; if (!args) @@ -314,31 +311,30 @@ msgtlvlen += 4 /* charset */ + args->msglen; } - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, msgtlvlen+128))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, msgtlvlen+128); /* XXX - should be optional */ - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* Generate an ICBM cookie */ aim_icbm_makecookie(cookie); /* ICBM header */ - aim_im_puticbm(&fr->data, cookie, 0x0001, args->destsn); + aim_im_puticbm(&frame->data, cookie, 0x0001, args->destsn); /* Message TLV (type 0x0002) */ - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, msgtlvlen); + byte_stream_put16(&frame->data, 0x0002); + byte_stream_put16(&frame->data, msgtlvlen); /* Features TLV (type 0x0501) */ - aimbs_put16(&fr->data, 0x0501); + byte_stream_put16(&frame->data, 0x0501); if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) { - aimbs_put16(&fr->data, args->featureslen); - aimbs_putraw(&fr->data, args->features, args->featureslen); + byte_stream_put16(&frame->data, args->featureslen); + byte_stream_putraw(&frame->data, args->features, args->featureslen); } else { - aimbs_put16(&fr->data, sizeof(deffeatures)); - aimbs_putraw(&fr->data, deffeatures, sizeof(deffeatures)); + byte_stream_put16(&frame->data, sizeof(deffeatures)); + byte_stream_putraw(&frame->data, deffeatures, sizeof(deffeatures)); } if (args->flags & AIM_IMFLAGS_MULTIPART) { @@ -346,42 +342,42 @@ /* Insert each message part in a TLV (type 0x0101) */ for (sec = args->mpmsg->parts; sec; sec = sec->next) { - aimbs_put16(&fr->data, 0x0101); - aimbs_put16(&fr->data, sec->datalen + 4); - aimbs_put16(&fr->data, sec->charset); - aimbs_put16(&fr->data, sec->charsubset); - aimbs_putraw(&fr->data, (guchar *)sec->data, sec->datalen); + byte_stream_put16(&frame->data, 0x0101); + byte_stream_put16(&frame->data, sec->datalen + 4); + byte_stream_put16(&frame->data, sec->charset); + byte_stream_put16(&frame->data, sec->charsubset); + byte_stream_putraw(&frame->data, (guchar *)sec->data, sec->datalen); } } else { /* Insert message text in a TLV (type 0x0101) */ - aimbs_put16(&fr->data, 0x0101); + byte_stream_put16(&frame->data, 0x0101); /* Message block length */ - aimbs_put16(&fr->data, args->msglen + 0x04); + byte_stream_put16(&frame->data, args->msglen + 0x04); /* Character set */ - aimbs_put16(&fr->data, args->charset); - aimbs_put16(&fr->data, args->charsubset); + byte_stream_put16(&frame->data, args->charset); + byte_stream_put16(&frame->data, args->charsubset); /* Message. Not terminated */ - aimbs_putraw(&fr->data, (guchar *)args->msg, args->msglen); + byte_stream_putraw(&frame->data, (guchar *)args->msg, args->msglen); } /* Set the Autoresponse flag */ if (args->flags & AIM_IMFLAGS_AWAY) { - aimbs_put16(&fr->data, 0x0004); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0004); + byte_stream_put16(&frame->data, 0x0000); } else if (args->flags & AIM_IMFLAGS_ACK) { /* Set the Request Acknowledge flag */ - aimbs_put16(&fr->data, 0x0003); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0003); + byte_stream_put16(&frame->data, 0x0000); } if (args->flags & AIM_IMFLAGS_OFFLINE) { - aimbs_put16(&fr->data, 0x0006); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0006); + byte_stream_put16(&frame->data, 0x0000); } /* @@ -390,12 +386,12 @@ * IMs and when you change your icon. */ if (args->flags & AIM_IMFLAGS_HASICON) { - aimbs_put16(&fr->data, 0x0008); - aimbs_put16(&fr->data, 0x000c); - aimbs_put32(&fr->data, args->iconlen); - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, args->iconsum); - aimbs_put32(&fr->data, args->iconstamp); + byte_stream_put16(&frame->data, 0x0008); + byte_stream_put16(&frame->data, 0x000c); + byte_stream_put32(&frame->data, args->iconlen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, args->iconsum); + byte_stream_put32(&frame->data, args->iconstamp); } /* @@ -403,14 +399,14 @@ * XXX - Every time? Surely not... */ if (args->flags & AIM_IMFLAGS_BUDDYREQ) { - aimbs_put16(&fr->data, 0x0009); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0009); + byte_stream_put16(&frame->data, 0x0000); } - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); /* clean out SNACs over 60sec old */ - aim_cleansnacs(sess, 60); + aim_cleansnacs(od, 60); return 0; } @@ -425,7 +421,7 @@ * that requires an explicit message length. Use aim_im_sendch1_ext(). * */ -faim_export int aim_im_sendch1(OscarSession *sess, const char *sn, guint16 flags, const char *msg) +int aim_im_sendch1(OscarData *od, const char *sn, guint16 flags, const char *msg) { struct aim_sendimext_args args; @@ -439,16 +435,16 @@ /* Make these don't get set by accident -- they need aim_im_sendch1_ext */ args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON | AIM_IMFLAGS_MULTIPART); - return aim_im_sendch1_ext(sess, &args); + return aim_im_sendch1_ext(od, &args); } /* * Subtype 0x0006 - Send a chat invitation. */ -faim_export int aim_im_sendch2_chatinvite(OscarSession *sess, const char *sn, const char *msg, guint16 exchange, const char *roomname, guint16 instance) +int aim_im_sendch2_chatinvite(OscarData *od, const char *sn, const char *msg, guint16 exchange, const char *roomname, guint16 instance) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; IcbmCookie *msgcookie; struct aim_invite_priv *priv; @@ -458,7 +454,7 @@ int hdrlen; ByteStream hdrbs; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; if (!sn || !msg || !roomname) @@ -466,27 +462,25 @@ aim_icbm_makecookie(cookie); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg)); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* XXX should be uncached by an unwritten 'invite accept' handler */ - if ((priv = malloc(sizeof(struct aim_invite_priv)))) { - priv->sn = strdup(sn); - priv->roomname = strdup(roomname); - priv->exchange = exchange; - priv->instance = instance; - } + priv = malloc(sizeof(struct aim_invite_priv)); + priv->sn = strdup(sn); + priv->roomname = strdup(roomname); + priv->exchange = exchange; + priv->instance = instance; if ((msgcookie = aim_mkcookie(cookie, AIM_COOKIETYPE_INVITE, priv))) - aim_cachecookie(sess, msgcookie); + aim_cachecookie(od, msgcookie); else free(priv); /* ICBM Header */ - aim_im_puticbm(&fr->data, cookie, 0x0002, sn); + aim_im_puticbm(&frame->data, cookie, 0x0002, sn); /* * TLV t(0005) @@ -500,11 +494,11 @@ */ hdrlen = 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2; hdr = malloc(hdrlen); - aim_bstream_init(&hdrbs, hdr, hdrlen); - - aimbs_put16(&hdrbs, 0x0000); /* Unknown! */ - aimbs_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */ - aimbs_putcaps(&hdrbs, AIM_CAPS_CHAT); + byte_stream_init(&hdrbs, hdr, hdrlen); + + byte_stream_put16(&hdrbs, 0x0000); /* Unknown! */ + byte_stream_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */ + byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_CHAT); aim_tlvlist_add_16(&itl, 0x000a, 0x0001); aim_tlvlist_add_noval(&itl, 0x000f); @@ -512,15 +506,15 @@ aim_tlvlist_add_chatroom(&itl, 0x2711, exchange, roomname, instance); aim_tlvlist_write(&hdrbs, &itl); - aim_tlvlist_add_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr); - - aim_tlvlist_write(&fr->data, &otl); + aim_tlvlist_add_raw(&otl, 0x0005, byte_stream_curpos(&hdrbs), hdr); + + aim_tlvlist_write(&frame->data, &otl); free(hdr); aim_tlvlist_free(&itl); aim_tlvlist_free(&otl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -531,14 +525,14 @@ * This is also performance sensitive. (If you can believe it...) * */ -faim_export int aim_im_sendch2_icon(OscarSession *sess, const char *sn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum) +int aim_im_sendch2_icon(OscarData *od, const char *sn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; guchar cookie[8]; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; if (!sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN)) @@ -546,51 +540,50 @@ aim_icbm_makecookie(cookie); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ - aim_im_puticbm(&fr->data, cookie, 0x0002, sn); + aim_im_puticbm(&frame->data, cookie, 0x0002, sn); /* * TLV t(0005) * * Encompasses everything below. */ - aimbs_put16(&fr->data, 0x0005); - aimbs_put16(&fr->data, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT)); - - aimbs_put16(&fr->data, 0x0000); - aimbs_putraw(&fr->data, cookie, 8); - aimbs_putcaps(&fr->data, AIM_CAPS_BUDDYICON); + byte_stream_put16(&frame->data, 0x0005); + byte_stream_put16(&frame->data, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT)); + + byte_stream_put16(&frame->data, 0x0000); + byte_stream_putraw(&frame->data, cookie, 8); + byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_BUDDYICON); /* TLV t(000a) */ - aimbs_put16(&fr->data, 0x000a); - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, 0x0001); + byte_stream_put16(&frame->data, 0x000a); + byte_stream_put16(&frame->data, 0x0002); + byte_stream_put16(&frame->data, 0x0001); /* TLV t(000f) */ - aimbs_put16(&fr->data, 0x000f); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x000f); + byte_stream_put16(&frame->data, 0x0000); /* TLV t(2711) */ - aimbs_put16(&fr->data, 0x2711); - aimbs_put16(&fr->data, 4+4+4+iconlen+strlen(AIM_ICONIDENT)); - aimbs_put16(&fr->data, 0x0000); - aimbs_put16(&fr->data, iconsum); - aimbs_put32(&fr->data, iconlen); - aimbs_put32(&fr->data, stamp); - aimbs_putraw(&fr->data, icon, iconlen); - aimbs_putstr(&fr->data, AIM_ICONIDENT); + byte_stream_put16(&frame->data, 0x2711); + byte_stream_put16(&frame->data, 4+4+4+iconlen+strlen(AIM_ICONIDENT)); + byte_stream_put16(&frame->data, 0x0000); + byte_stream_put16(&frame->data, iconsum); + byte_stream_put32(&frame->data, iconlen); + byte_stream_put32(&frame->data, stamp); + byte_stream_putraw(&frame->data, icon, iconlen); + byte_stream_putstr(&frame->data, AIM_ICONIDENT); /* TLV t(0003) */ - aimbs_put16(&fr->data, 0x0003); - aimbs_put16(&fr->data, 0x0000); - - aim_tx_enqueue(sess, fr); + byte_stream_put16(&frame->data, 0x0003); + byte_stream_put16(&frame->data, 0x0000); + + flap_connection_send(conn, frame); return 0; } @@ -610,16 +603,16 @@ * make an interface similar to what AOL actually uses. But I'm not using COM. * */ -faim_export int aim_im_sendch2_rtfmsg(OscarSession *sess, struct aim_sendrtfmsg_args *args) +int aim_im_sendch2_rtfmsg(OscarData *od, struct aim_sendrtfmsg_args *args) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; guchar cookie[8]; - const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */ + const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* OSCAR_CAPABILITY_ICQRTF capability in string form */ int servdatalen; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; if (!args || !args->destsn || !args->rtfmsg) @@ -629,459 +622,553 @@ aim_icbm_makecookie(cookie); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+128+servdatalen))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 10+128+servdatalen); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ - aim_im_puticbm(&fr->data, cookie, 0x0002, args->destsn); + aim_im_puticbm(&frame->data, cookie, 0x0002, args->destsn); /* TLV t(0005) - Encompasses everything below. */ - aimbs_put16(&fr->data, 0x0005); - aimbs_put16(&fr->data, 2+8+16 + 2+2+2 + 2+2 + 2+2+servdatalen); - - aimbs_put16(&fr->data, 0x0000); - aimbs_putraw(&fr->data, cookie, 8); - aimbs_putcaps(&fr->data, AIM_CAPS_ICQSERVERRELAY); + byte_stream_put16(&frame->data, 0x0005); + byte_stream_put16(&frame->data, 2+8+16 + 2+2+2 + 2+2 + 2+2+servdatalen); + + byte_stream_put16(&frame->data, 0x0000); + byte_stream_putraw(&frame->data, cookie, 8); + byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_ICQSERVERRELAY); /* t(000a) l(0002) v(0001) */ - aimbs_put16(&fr->data, 0x000a); - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, 0x0001); + byte_stream_put16(&frame->data, 0x000a); + byte_stream_put16(&frame->data, 0x0002); + byte_stream_put16(&frame->data, 0x0001); /* t(000f) l(0000) v() */ - aimbs_put16(&fr->data, 0x000f); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x000f); + byte_stream_put16(&frame->data, 0x0000); /* Service Data TLV */ - aimbs_put16(&fr->data, 0x2711); - aimbs_put16(&fr->data, servdatalen); - - aimbs_putle16(&fr->data, 11 + 16 /* 11 + (sizeof CLSID) */); - aimbs_putle16(&fr->data, 9); - aimbs_putcaps(&fr->data, AIM_CAPS_EMPTY); - aimbs_putle16(&fr->data, 0); - aimbs_putle32(&fr->data, 0); - aimbs_putle8(&fr->data, 0); - aimbs_putle16(&fr->data, 0x03ea); /* trid1 */ - - aimbs_putle16(&fr->data, 14); - aimbs_putle16(&fr->data, 0x03eb); /* trid2 */ - aimbs_putle32(&fr->data, 0); - aimbs_putle32(&fr->data, 0); - aimbs_putle32(&fr->data, 0); - - aimbs_putle16(&fr->data, 0x0001); - aimbs_putle32(&fr->data, 0); - aimbs_putle16(&fr->data, strlen(args->rtfmsg)+1); - aimbs_putraw(&fr->data, (const guint8 *)args->rtfmsg, strlen(args->rtfmsg)+1); - - aimbs_putle32(&fr->data, args->fgcolor); - aimbs_putle32(&fr->data, args->bgcolor); - aimbs_putle32(&fr->data, strlen(rtfcap)+1); - aimbs_putraw(&fr->data, (const guint8 *)rtfcap, strlen(rtfcap)+1); - - aim_tx_enqueue(sess, fr); + byte_stream_put16(&frame->data, 0x2711); + byte_stream_put16(&frame->data, servdatalen); + + byte_stream_putle16(&frame->data, 11 + 16 /* 11 + (sizeof CLSID) */); + byte_stream_putle16(&frame->data, 9); + byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_EMPTY); + byte_stream_putle16(&frame->data, 0); + byte_stream_putle32(&frame->data, 0); + byte_stream_putle8(&frame->data, 0); + byte_stream_putle16(&frame->data, 0x03ea); /* trid1 */ + + byte_stream_putle16(&frame->data, 14); + byte_stream_putle16(&frame->data, 0x03eb); /* trid2 */ + byte_stream_putle32(&frame->data, 0); + byte_stream_putle32(&frame->data, 0); + byte_stream_putle32(&frame->data, 0); + + byte_stream_putle16(&frame->data, 0x0001); + byte_stream_putle32(&frame->data, 0); + byte_stream_putle16(&frame->data, strlen(args->rtfmsg)+1); + byte_stream_putraw(&frame->data, (const guint8 *)args->rtfmsg, strlen(args->rtfmsg)+1); + + byte_stream_putle32(&frame->data, args->fgcolor); + byte_stream_putle32(&frame->data, args->bgcolor); + byte_stream_putle32(&frame->data, strlen(rtfcap)+1); + byte_stream_putraw(&frame->data, (const guint8 *)rtfcap, strlen(rtfcap)+1); + + flap_connection_send(conn, frame); return 0; } /** - * Subtype 0x0006 - Send an "I want to directly connect to you" message - * + * Cancel a rendezvous invitation. It could be an invitation to + * establish a direct connection, or a file-send, or a chat invite. */ -faim_export int aim_im_sendch2_odcrequest(OscarSession *sess, guchar *usercookie, gboolean usecookie, const char *sn, const guint8 *ip, guint16 port) +void +aim_im_sendch2_cancel(PeerConnection *peer_conn) { - OscarConnection *conn; - FlapFrame *fr; + OscarData *od; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - guchar cookie[8]; + aim_tlvlist_t *tl = NULL, *itl = NULL; + int hdrlen; + guint8 *hdr; + ByteStream hdrbs; + + od = peer_conn->od; + conn = flap_connection_findbygroup(od, 0x0004); + if (conn == NULL) + return; + + frame = flap_frame_new(od, 0x02, 128+strlen(peer_conn->sn)); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); + + /* ICBM header */ + aim_im_puticbm(&frame->data, peer_conn->cookie, 0x0002, peer_conn->sn); + + aim_tlvlist_add_noval(&tl, 0x0003); + + hdrlen = 64; + hdr = malloc(hdrlen); + byte_stream_init(&hdrbs, hdr, hdrlen); + + byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_CANCEL); + byte_stream_putraw(&hdrbs, peer_conn->cookie, 8); + byte_stream_putcaps(&hdrbs, peer_conn->type); + + /* This TLV means "cancel!" */ + aim_tlvlist_add_16(&itl, 0x000b, 0x0001); + aim_tlvlist_write(&hdrbs, &itl); + + aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdr); + + aim_tlvlist_write(&frame->data, &tl); + + free(hdr); + aim_tlvlist_free(&itl); + aim_tlvlist_free(&tl); + + flap_connection_send(conn, frame); +} + +/** + * Subtype 0x0006 - Send an "I accept and I've connected to + * you" message. + */ +void +aim_im_sendch2_connected(PeerConnection *peer_conn) +{ + OscarData *od; + FlapConnection *conn; + FlapFrame *frame; + aim_snacid_t snacid; + + od = peer_conn->od; + conn = flap_connection_findbygroup(od, 0x0004); + if (conn == NULL) + return; + + frame = flap_frame_new(od, 0x02, 10 + 11+strlen(peer_conn->sn) + 4+2+8+16); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); + + /* ICBM header */ + aim_im_puticbm(&frame->data, peer_conn->cookie, 0x0002, peer_conn->sn); + + byte_stream_put16(&frame->data, 0x0005); + byte_stream_put16(&frame->data, 0x001a); + byte_stream_put16(&frame->data, AIM_RENDEZVOUS_CONNECTED); + byte_stream_putraw(&frame->data, peer_conn->cookie, 8); + byte_stream_putcaps(&frame->data, peer_conn->type); + + flap_connection_send(conn, frame); +} + +/** + * Subtype 0x0006 - Send a direct connect rendezvous ICBM. This + * could have a number of meanings, depending on the content: + * "I want you to connect to me" + * "I want to connect to you" + * "I want to connect through a proxy server" + */ +void +aim_im_sendch2_odc_requestdirect(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 port, guint16 requestnumber) +{ + FlapConnection *conn; + FlapFrame *frame; + aim_snacid_t snacid; aim_tlvlist_t *tl = NULL, *itl = NULL; int hdrlen; guint8 *hdr; ByteStream hdrbs; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) - return -EINVAL; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(sn)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); - - /* - * Generate a random message cookie - * - * This cookie needs to be alphanumeric and NULL-terminated to be - * TOC-compatible. - * - * XXX - have I mentioned these should be generated in msgcookie.c? - * - */ - - if (usercookie && usecookie) /* allow user-specified cookie */ - memcpy(cookie, usercookie, 8); - else - aim_icbm_makecookie(cookie); - cookie[7] = '\0'; - - if (usercookie && !usecookie) - memcpy(cookie, usercookie, 8); + conn = flap_connection_findbygroup(od, 0x0004); + if (conn == NULL) + return; + + frame = flap_frame_new(od, 0x02, 256+strlen(sn)); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ - aim_im_puticbm(&fr->data, cookie, 0x0002, sn); + aim_im_puticbm(&frame->data, cookie, 0x0002, sn); aim_tlvlist_add_noval(&tl, 0x0003); - hdrlen = 2+8+16+6+8+6+4; + hdrlen = 128; hdr = malloc(hdrlen); - aim_bstream_init(&hdrbs, hdr, hdrlen); - - aimbs_put16(&hdrbs, 0x0000); - aimbs_putraw(&hdrbs, cookie, 8); - aimbs_putcaps(&hdrbs, AIM_CAPS_DIRECTIM); - - aim_tlvlist_add_16(&itl, 0x000a, 0x0001); + byte_stream_init(&hdrbs, hdr, hdrlen); + + byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE); + byte_stream_putraw(&hdrbs, cookie, 8); + byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM); + + aim_tlvlist_add_raw(&itl, 0x0002, 4, ip); aim_tlvlist_add_raw(&itl, 0x0003, 4, ip); aim_tlvlist_add_16(&itl, 0x0005, port); + aim_tlvlist_add_16(&itl, 0x000a, requestnumber); aim_tlvlist_add_noval(&itl, 0x000f); - aim_tlvlist_write(&hdrbs, &itl); - aim_tlvlist_add_raw(&tl, 0x0005, aim_bstream_curpos(&hdrbs), hdr); - - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdr); + + aim_tlvlist_write(&frame->data, &tl); free(hdr); aim_tlvlist_free(&itl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); - - return 0; + flap_connection_send(conn, frame); +} + +/** + * Subtype 0x0006 - Send a direct connect rendezvous ICBM asking the + * remote user to connect to us via a proxy server. + */ +void +aim_im_sendch2_odc_requestproxy(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 pin, guint16 requestnumber) +{ + FlapConnection *conn; + FlapFrame *frame; + aim_snacid_t snacid; + aim_tlvlist_t *tl = NULL, *itl = NULL; + int hdrlen; + guint8 *hdr; + ByteStream hdrbs; + guint8 ip_comp[4]; + + conn = flap_connection_findbygroup(od, 0x0004); + if (conn == NULL) + return; + + frame = flap_frame_new(od, 0x02, 256+strlen(sn)); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); + + /* ICBM header */ + aim_im_puticbm(&frame->data, cookie, 0x0002, sn); + + aim_tlvlist_add_noval(&tl, 0x0003); + + hdrlen = 128; + hdr = malloc(hdrlen); + byte_stream_init(&hdrbs, hdr, hdrlen); + + byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE); + byte_stream_putraw(&hdrbs, cookie, 8); + byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM); + + aim_tlvlist_add_raw(&itl, 0x0002, 4, ip); + aim_tlvlist_add_raw(&itl, 0x0003, 4, ip); + aim_tlvlist_add_16(&itl, 0x0005, pin); + aim_tlvlist_add_16(&itl, 0x000a, requestnumber); + aim_tlvlist_add_noval(&itl, 0x000f); + aim_tlvlist_add_noval(&itl, 0x0010); + + /* Send the bitwise complement of the port and ip. As a check? */ + ip_comp[0] = ~ip[0]; + ip_comp[1] = ~ip[1]; + ip_comp[2] = ~ip[2]; + ip_comp[3] = ~ip[3]; + aim_tlvlist_add_raw(&itl, 0x0016, 4, ip_comp); + aim_tlvlist_add_16(&itl, 0x0017, ~pin); + + aim_tlvlist_write(&hdrbs, &itl); + + aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdr); + + aim_tlvlist_write(&frame->data, &tl); + + free(hdr); + aim_tlvlist_free(&itl); + aim_tlvlist_free(&tl); + + flap_connection_send(conn, frame); } /** * Subtype 0x0006 - Send an "I want to send you this file" message * */ -faim_export int aim_im_sendch2_sendfile_ask(OscarSession *sess, PeerConnection *peer_connection) +void +aim_im_sendch2_sendfile_requestdirect(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 port, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - aim_tlvlist_t *tl=NULL, *subtl=NULL; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !peer_connection) - return -EINVAL; - - /* The cookie must already have been generated by this point */ - - { /* Create the subTLV chain */ - guint8 *buf; - int buflen; - ByteStream bs; - guint8 ip[4]; - guint8 ip_comp[4]; /* The bitwise complement of the ip */ - char *nexttoken; - int i; - - /* In a stage 2 proxied transfer & a transfer redirect, we send a second "reply request" - * Being the second request for this transfer, its request number is 2 - * You can fill in the blank for a stage 3's request number... */ - if ((peer_connection->send_or_recv == AIM_XFER_RECV && peer_connection->stage == AIM_XFER_PROXY_STG2) - || (peer_connection->send_or_recv == AIM_XFER_RECV - && peer_connection->stage == AIM_XFER_PROXY_STG3) - || peer_connection->method == AIM_XFER_REDIR) - aim_tlvlist_add_16(&subtl, 0x000a, 0x0002); - else if(peer_connection->send_or_recv == AIM_XFER_SEND && peer_connection->stage == AIM_XFER_PROXY_STG3) - aim_tlvlist_add_16(&subtl, 0x000a, 0x0003); - else - aim_tlvlist_add_16(&subtl, 0x000a, 0x0001); - - /* This is usually necessary, but ruins a redirect and a stg3 proxy request */ - if(!(peer_connection->send_or_recv == AIM_XFER_RECV - && (peer_connection->method == AIM_XFER_REDIR || peer_connection->stage == AIM_XFER_PROXY_STG3))) { - aim_tlvlist_add_noval(&subtl, 0x000f); - } - - /* If the following is ever enabled, ensure that it is not sent with a receive redirect - * or stage 3 proxy redirect for a file receive (same conditions for sending 0x000f above) */ -/* aim_tlvlist_add_raw(&subtl, 0x000e, 2, "en"); - aim_tlvlist_add_raw(&subtl, 0x000d, 8, "us-ascii"); - aim_tlvlist_add_raw(&subtl, 0x000c, 24, "Please accept this file."); */ - /* XXX - Change peer_connection->clientip to an array of 4 bytes */ - if (peer_connection->clientip) { - i = 0; - nexttoken = strtok(peer_connection->clientip, "."); - while (nexttoken && i<4) { - ip[i] = atoi(nexttoken); - ip_comp[i] = ~ip[i]; - nexttoken = strtok(NULL, "."); - i++; - } - - /* If there is no proxyip, we must fill it in with the clientip */ - if(!peer_connection->proxyip) { - aim_tlvlist_add_raw(&subtl, 0x0002, 4, ip); - aim_tlvlist_add_raw(&subtl, 0x0016, 4, ip_comp); /* check? value */ - } - - aim_tlvlist_add_raw(&subtl, 0x0003, 4, ip); - } - - /* Don't send the proxyip & accompanying info during a receive redirect or stg3 proxy request */ - if(!(peer_connection->send_or_recv == AIM_XFER_RECV - && (peer_connection->method == AIM_XFER_REDIR || peer_connection->stage == AIM_XFER_PROXY_STG3))) { - if (peer_connection->proxyip) { /* Generate the proxyip */ - i = 0; - nexttoken = strtok(peer_connection->proxyip, "."); - while (nexttoken && i<4) { - ip[i] = atoi(nexttoken); - ip_comp[i] = ~ip[i]; - nexttoken = strtok(NULL, "."); - i++; - } - aim_tlvlist_add_raw(&subtl, 0x0002, 4, ip); - /* This zero-length TLV specifies a proxy will be used */ - aim_tlvlist_add_noval(&subtl, 0x0010); - - /* Proxied transfers fail without this next (check?) value */ - aim_tlvlist_add_raw(&subtl, 0x0016, 4, ip_comp); - } - } - - /* Don't send the port & its check during a stage 3 proxy request */ - if(!(peer_connection->send_or_recv == AIM_XFER_RECV && peer_connection->stage == AIM_XFER_PROXY_STG3)) { - aim_tlvlist_add_16(&subtl, 0x0005, peer_connection->port); - - /* Check value? Bitwise complement of the port */ - aim_tlvlist_add_16(&subtl, 0x0017, ~(peer_connection->port)); - } - - /* winAIM gets mad at us if we send too much info during a send redirect or stg3 proxy request */ - if(!(peer_connection->send_or_recv == AIM_XFER_RECV - && (peer_connection->method == AIM_XFER_REDIR || peer_connection->stage == AIM_XFER_PROXY_STG3))) { - /* TLV t(2711) */ - buflen = 2+2+4+strlen(peer_connection->fh.name)+1; - buf = malloc(buflen); - aim_bstream_init(&bs, buf, buflen); - aimbs_put16(&bs, (peer_connection->fh.totfiles > 1) ? 0x0002 : 0x0001); - aimbs_put16(&bs, peer_connection->fh.totfiles); - aimbs_put32(&bs, peer_connection->fh.totsize); - - /* Filename - NULL terminated, for some odd reason */ - aimbs_putstr(&bs, peer_connection->fh.name); - aimbs_put8(&bs, 0x00); - - aim_tlvlist_add_raw(&subtl, 0x2711, bs.len, bs.data); - free(buf); - } - } - - { /* Create the main TLV chain */ - guint8 *buf; - int buflen; - ByteStream bs; - - /* TLV t(0005) - Encompasses everything from above. Gee. */ - buflen = 2+8+16+aim_tlvlist_size(&subtl); - buf = malloc(buflen); - aim_bstream_init(&bs, buf, buflen); - aimbs_put16(&bs, AIM_RENDEZVOUS_PROPOSE); - aimbs_putraw(&bs, peer_connection->cookie, 8); - aimbs_putcaps(&bs, AIM_CAPS_SENDFILE); - aim_tlvlist_write(&bs, &subtl); - aim_tlvlist_free(&subtl); - aim_tlvlist_add_raw(&tl, 0x0005, bs.len, bs.data); - free(buf); - - /* TLV t(0003) - Request an ack */ - aim_tlvlist_add_noval(&tl, 0x0003); - } - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(peer_connection->sn) + aim_tlvlist_size(&tl)))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, peer_connection->cookie, sizeof(peer_connection->cookie)); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + aim_tlvlist_t *tl = NULL, *itl = NULL; + int hdrlen, buflen; + guint8 *hdr; + ByteStream hdrbs; + + conn = flap_connection_findbygroup(od, 0x0004); + if (conn == NULL) + return; + + frame = flap_frame_new(od, 0x02, 1024); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ - aim_im_puticbm(&fr->data, peer_connection->cookie, 0x0002, peer_connection->sn); - - /* All that crap from above (the 0x0005 TLV and the 0x0003 TLV) */ - aim_tlvlist_write(&fr->data, &tl); + aim_im_puticbm(&frame->data, cookie, 0x0002, sn); + + aim_tlvlist_add_noval(&tl, 0x0003); + + hdrlen = 512; + hdr = malloc(hdrlen); + byte_stream_init(&hdrbs, hdr, hdrlen); + + byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE); + byte_stream_putraw(&hdrbs, cookie, 8); + byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE); + + aim_tlvlist_add_raw(&itl, 0x0002, 4, ip); + aim_tlvlist_add_raw(&itl, 0x0003, 4, ip); + aim_tlvlist_add_16(&itl, 0x0005, port); + aim_tlvlist_add_16(&itl, 0x000a, requestnumber); + aim_tlvlist_add_noval(&itl, 0x000f); + /* TODO: Send 0x0016 and 0x0017 */ + +#if 0 + /* TODO: If the following is ever enabled, ensure that it is + * not sent with a receive redirect or stage 3 proxy + * redirect for a file receive (same conditions for + * sending 0x000f above) + */ + aim_tlvlist_add_raw(&itl, 0x000e, 2, "en"); + aim_tlvlist_add_raw(&itl, 0x000d, 8, "us-ascii"); + aim_tlvlist_add_raw(&itl, 0x000c, 24, "Please accept this file."); +#endif + + if (filename != NULL) + { + ByteStream bs; + + /* Begin TLV t(2711) */ + buflen = 2+2+4+strlen(filename)+1; + byte_stream_init(&bs, malloc(buflen), buflen); + byte_stream_put16(&bs, (numfiles > 1) ? 0x0002 : 0x0001); + byte_stream_put16(&bs, numfiles); + byte_stream_put32(&bs, size); + + /* Filename - NULL terminated, for some odd reason */ + byte_stream_putstr(&bs, filename); + byte_stream_put8(&bs, 0x00); + + aim_tlvlist_add_raw(&itl, 0x2711, bs.len, bs.data); + free(bs.data); + /* End TLV t(2711) */ + } + + aim_tlvlist_write(&hdrbs, &itl); + aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdr); + + aim_tlvlist_write(&frame->data, &tl); + + free(hdr); + aim_tlvlist_free(&itl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); - - return 0; + flap_connection_send(conn, frame); } /** - * Subtype 0x0006 - Send an "I will accept this file" message? - * - * @param rendid Capability type (AIM_CAPS_GETFILE or AIM_CAPS_SENDFILE) + * Subtype 0x0006 - Send a sendfile connect rendezvous ICBM asking the + * remote user to connect to us via a proxy server. */ -faim_export int aim_im_sendch2_sendfile_accept(OscarSession *sess, PeerConnection *peer_connection) +void +aim_im_sendch2_sendfile_requestproxy(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 pin, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !peer_connection) - return -EINVAL; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(peer_connection->sn) + 4+2+8+16))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + aim_tlvlist_t *tl = NULL, *itl = NULL; + int hdrlen, buflen; + guint8 *hdr; + ByteStream hdrbs; + guint8 ip_comp[4]; + + conn = flap_connection_findbygroup(od, 0x0004); + if (conn == NULL) + return; + + frame = flap_frame_new(od, 0x02, 1024); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ - aim_im_puticbm(&fr->data, peer_connection->cookie, 0x0002, peer_connection->sn); - - aimbs_put16(&fr->data, 0x0005); - aimbs_put16(&fr->data, 0x001a); - aimbs_put16(&fr->data, AIM_RENDEZVOUS_ACCEPT); - aimbs_putraw(&fr->data, peer_connection->cookie, 8); - aimbs_putcaps(&fr->data, AIM_CAPS_SENDFILE); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/** - * Subtype 0x0006 - Send a "cancel this file transfer" message? - * - */ -faim_export int aim_im_sendch2_sendfile_cancel(OscarSession *sess, PeerConnection *peer_connection) -{ - OscarConnection *conn; - FlapFrame *fr; - aim_snacid_t snacid; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !peer_connection) - return -EINVAL; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(peer_connection->sn) + 4+2+8+16))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); - - /* ICBM header */ - aim_im_puticbm(&fr->data, peer_connection->cookie, 0x0002, peer_connection->sn); - - aimbs_put16(&fr->data, 0x0005); - aimbs_put16(&fr->data, 0x001a); - aimbs_put16(&fr->data, AIM_RENDEZVOUS_CANCEL); - aimbs_putraw(&fr->data, (const guchar *)peer_connection->cookie, 8); - aimbs_putcaps(&fr->data, AIM_CAPS_SENDFILE); - - aim_tx_enqueue(sess, fr); - - return 0; + aim_im_puticbm(&frame->data, cookie, 0x0002, sn); + + aim_tlvlist_add_noval(&tl, 0x0003); + + hdrlen = 512; + hdr = malloc(hdrlen); + byte_stream_init(&hdrbs, hdr, hdrlen); + + byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE); + byte_stream_putraw(&hdrbs, cookie, 8); + byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE); + + aim_tlvlist_add_raw(&itl, 0x0002, 4, ip); + aim_tlvlist_add_raw(&itl, 0x0003, 4, ip); + aim_tlvlist_add_16(&itl, 0x0005, pin); + aim_tlvlist_add_16(&itl, 0x000a, requestnumber); + aim_tlvlist_add_noval(&itl, 0x000f); + aim_tlvlist_add_noval(&itl, 0x0010); + + /* Send the bitwise complement of the port and ip. As a check? */ + ip_comp[0] = ~ip[0]; + ip_comp[1] = ~ip[1]; + ip_comp[2] = ~ip[2]; + ip_comp[3] = ~ip[3]; + aim_tlvlist_add_raw(&itl, 0x0016, 4, ip_comp); + aim_tlvlist_add_16(&itl, 0x0017, ~pin); + +#if 0 + /* TODO: If the following is ever enabled, ensure that it is + * not sent with a receive redirect or stage 3 proxy + * redirect for a file receive (same conditions for + * sending 0x000f above) + */ + aim_tlvlist_add_raw(&itl, 0x000e, 2, "en"); + aim_tlvlist_add_raw(&itl, 0x000d, 8, "us-ascii"); + aim_tlvlist_add_raw(&itl, 0x000c, 24, "Please accept this file."); +#endif + + if (filename != NULL) + { + ByteStream bs; + + /* Begin TLV t(2711) */ + buflen = 2+2+4+strlen(filename)+1; + byte_stream_init(&bs, malloc(buflen), buflen); + byte_stream_put16(&bs, (numfiles > 1) ? 0x0002 : 0x0001); + byte_stream_put16(&bs, numfiles); + byte_stream_put32(&bs, size); + + /* Filename - NULL terminated, for some odd reason */ + byte_stream_putstr(&bs, filename); + byte_stream_put8(&bs, 0x00); + + aim_tlvlist_add_raw(&itl, 0x2711, bs.len, bs.data); + free(bs.data); + /* End TLV t(2711) */ + } + + aim_tlvlist_write(&hdrbs, &itl); + + aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdr); + + aim_tlvlist_write(&frame->data, &tl); + + free(hdr); + aim_tlvlist_free(&itl); + aim_tlvlist_free(&tl); + + flap_connection_send(conn, frame); } /** * Subtype 0x0006 - Request the status message of the given ICQ user. * - * @param sess The oscar session. + * @param od The oscar session. * @param sn The UIN of the user of whom you wish to request info. * @param type The type of info you wish to request. This should be the current * state of the user, as one of the AIM_ICQ_STATE_* defines. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_im_sendch2_geticqaway(OscarSession *sess, const char *sn, int type) +int aim_im_sendch2_geticqaway(OscarData *od, const char *sn, int type) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; guchar cookie[8]; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !sn) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)) || !sn) return -EINVAL; aim_icbm_makecookie(cookie); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ - aim_im_puticbm(&fr->data, cookie, 0x0002, sn); + aim_im_puticbm(&frame->data, cookie, 0x0002, sn); /* TLV t(0005) - Encompasses almost everything below. */ - aimbs_put16(&fr->data, 0x0005); /* T */ - aimbs_put16(&fr->data, 0x005e); /* L */ + byte_stream_put16(&frame->data, 0x0005); /* T */ + byte_stream_put16(&frame->data, 0x005e); /* L */ { /* V */ - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); /* Cookie */ - aimbs_putraw(&fr->data, cookie, 8); + byte_stream_putraw(&frame->data, cookie, 8); /* Put the 16 byte server relay capability */ - aimbs_putcaps(&fr->data, AIM_CAPS_ICQSERVERRELAY); + byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_ICQSERVERRELAY); /* TLV t(000a) */ - aimbs_put16(&fr->data, 0x000a); - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, 0x0001); + byte_stream_put16(&frame->data, 0x000a); + byte_stream_put16(&frame->data, 0x0002); + byte_stream_put16(&frame->data, 0x0001); /* TLV t(000f) */ - aimbs_put16(&fr->data, 0x000f); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x000f); + byte_stream_put16(&frame->data, 0x0000); /* TLV t(2711) */ - aimbs_put16(&fr->data, 0x2711); - aimbs_put16(&fr->data, 0x0036); + byte_stream_put16(&frame->data, 0x2711); + byte_stream_put16(&frame->data, 0x0036); { /* V */ - aimbs_putle16(&fr->data, 0x001b); /* L */ - aimbs_putle16(&fr->data, 0x0009); /* Protocol version */ - aimbs_putcaps(&fr->data, AIM_CAPS_EMPTY); - aimbs_putle16(&fr->data, 0x0000); /* Unknown */ - aimbs_putle16(&fr->data, 0x0001); /* Client features? */ - aimbs_putle16(&fr->data, 0x0000); /* Unknown */ - aimbs_putle8(&fr->data, 0x00); /* Unkizown */ - aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ - - aimbs_putle16(&fr->data, 0x000e); /* L */ - aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + byte_stream_putle16(&frame->data, 0x001b); /* L */ + byte_stream_putle16(&frame->data, 0x0009); /* Protocol version */ + byte_stream_putcaps(&frame->data, OSCAR_CAPABILITY_EMPTY); + byte_stream_putle16(&frame->data, 0x0000); /* Unknown */ + byte_stream_putle16(&frame->data, 0x0001); /* Client features? */ + byte_stream_putle16(&frame->data, 0x0000); /* Unknown */ + byte_stream_putle8(&frame->data, 0x00); /* Unkizown */ + byte_stream_putle16(&frame->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ + + byte_stream_putle16(&frame->data, 0x000e); /* L */ + byte_stream_putle16(&frame->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ + byte_stream_putle32(&frame->data, 0x00000000); /* Unknown */ + byte_stream_putle32(&frame->data, 0x00000000); /* Unknown */ + byte_stream_putle32(&frame->data, 0x00000000); /* Unknown */ /* The type of status message being requested */ if (type & AIM_ICQ_STATE_CHAT) - aimbs_putle16(&fr->data, 0x03ec); + byte_stream_putle16(&frame->data, 0x03ec); else if(type & AIM_ICQ_STATE_DND) - aimbs_putle16(&fr->data, 0x03eb); + byte_stream_putle16(&frame->data, 0x03eb); else if(type & AIM_ICQ_STATE_OUT) - aimbs_putle16(&fr->data, 0x03ea); + byte_stream_putle16(&frame->data, 0x03ea); else if(type & AIM_ICQ_STATE_BUSY) - aimbs_putle16(&fr->data, 0x03e9); + byte_stream_putle16(&frame->data, 0x03e9); else if(type & AIM_ICQ_STATE_AWAY) - aimbs_putle16(&fr->data, 0x03e8); - - aimbs_putle16(&fr->data, 0x0001); /* Status? */ - aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */ - aimbs_putle16(&fr->data, 0x0001); /* L */ - aimbs_putle8(&fr->data, 0x00); /* String of length L */ + byte_stream_putle16(&frame->data, 0x03e8); + + byte_stream_putle16(&frame->data, 0x0001); /* Status? */ + byte_stream_putle16(&frame->data, 0x0001); /* Priority of this message? */ + byte_stream_putle16(&frame->data, 0x0001); /* L */ + byte_stream_putle8(&frame->data, 0x00); /* String of length L */ } /* End TLV t(2711) */ } /* End TLV t(0005) */ /* TLV t(0003) */ - aimbs_put16(&fr->data, 0x0003); - aimbs_put16(&fr->data, 0x0000); - - aim_tx_enqueue(sess, fr); + byte_stream_put16(&frame->data, 0x0003); + byte_stream_put16(&frame->data, 0x0000); + + flap_connection_send(conn, frame); return 0; } @@ -1100,57 +1187,56 @@ * @param message The message you want to send, it should be null terminated. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_im_sendch4(OscarSession *sess, const char *sn, guint16 type, const char *message) +int aim_im_sendch4(OscarData *od, const char *sn, guint16 type, const char *message) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; guchar cookie[8]; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0002))) return -EINVAL; if (!sn || !type || !message) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+3+strlen(sn)+12+strlen(message)+1+4))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 10+8+3+strlen(sn)+12+strlen(message)+1+4); + + snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid); aim_icbm_makecookie(cookie); /* ICBM header */ - aim_im_puticbm(&fr->data, cookie, 0x0004, sn); + aim_im_puticbm(&frame->data, cookie, 0x0004, sn); /* * TLV t(0005) * * ICQ data (the UIN and the message). */ - aimbs_put16(&fr->data, 0x0005); - aimbs_put16(&fr->data, 4 + 2+2+strlen(message)+1); + byte_stream_put16(&frame->data, 0x0005); + byte_stream_put16(&frame->data, 4 + 2+2+strlen(message)+1); /* * Your UIN */ - aimbs_putle32(&fr->data, atoi(sess->sn)); + byte_stream_putle32(&frame->data, atoi(od->sn)); /* * TLV t(type) l(strlen(message)+1) v(message+NULL) */ - aimbs_putle16(&fr->data, type); - aimbs_putle16(&fr->data, strlen(message)+1); - aimbs_putraw(&fr->data, (const guint8 *)message, strlen(message)+1); + byte_stream_putle16(&frame->data, type); + byte_stream_putle16(&frame->data, strlen(message)+1); + byte_stream_putraw(&frame->data, (const guint8 *)message, strlen(message)+1); /* * TLV t(0006) l(0000) v() */ - aimbs_put16(&fr->data, 0x0006); - aimbs_put16(&fr->data, 0x0000); - - aim_tx_enqueue(sess, fr); + byte_stream_put16(&frame->data, 0x0006); + byte_stream_put16(&frame->data, 0x0000); + + flap_connection_send(conn, frame); return 0; } @@ -1158,7 +1244,7 @@ /* * XXX - I don't see when this would ever get called... */ -static int outgoingim(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int outgoingim(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1176,15 +1262,15 @@ aim_icbm_makecookie(cookie); /* Channel ID */ - channel = aimbs_get16(bs); + channel = byte_stream_get16(bs); if (channel != 0x01) { gaim_debug_misc("oscar", "icbm: ICBM recieved on unsupported channel. Ignoring. (chan = %04x)\n", channel); return 0; } - snlen = aimbs_get8(bs); - sn = aimbs_getstr(bs, snlen); + snlen = byte_stream_get8(bs); + sn = byte_stream_getstr(bs, snlen); tlvlist = aim_tlvlist_read(bs); @@ -1197,25 +1283,25 @@ ByteStream mbs; int featurelen, msglen; - aim_bstream_init(&mbs, msgblock->value, msgblock->length); - - aimbs_get8(&mbs); - aimbs_get8(&mbs); - for (featurelen = aimbs_get16(&mbs); featurelen; featurelen--) - aimbs_get8(&mbs); - aimbs_get8(&mbs); - aimbs_get8(&mbs); - - msglen = aimbs_get16(&mbs) - 4; /* final block length */ - - flag1 = aimbs_get16(&mbs); - flag2 = aimbs_get16(&mbs); - - msg = aimbs_getstr(&mbs, msglen); + byte_stream_init(&mbs, msgblock->value, msgblock->length); + + byte_stream_get8(&mbs); + byte_stream_get8(&mbs); + for (featurelen = byte_stream_get16(&mbs); featurelen; featurelen--) + byte_stream_get8(&mbs); + byte_stream_get8(&mbs); + byte_stream_get8(&mbs); + + msglen = byte_stream_get16(&mbs) - 4; /* final block length */ + + flag1 = byte_stream_get16(&mbs); + flag2 = byte_stream_get16(&mbs); + + msg = byte_stream_getstr(&mbs, msglen); } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, sn, msg, icbmflags, flag1, flag2); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, channel, sn, msg, icbmflags, flag1, flag2); free(sn); aim_tlvlist_free(&tlvlist); @@ -1260,7 +1346,7 @@ * know what you are doing, and/or you have something neat to do with it. * */ -faim_export int aim_mpmsg_init(OscarSession *sess, aim_mpmsg_t *mpm) +int aim_mpmsg_init(OscarData *od, aim_mpmsg_t *mpm) { memset(mpm, 0, sizeof(aim_mpmsg_t)); @@ -1268,12 +1354,11 @@ return 0; } -static int mpmsg_addsection(OscarSession *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, gchar *data, guint16 datalen) +static int mpmsg_addsection(OscarData *od, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, gchar *data, guint16 datalen) { aim_mpmsg_section_t *sec; - if (!(sec = malloc(sizeof(aim_mpmsg_section_t)))) - return -1; + sec = malloc(sizeof(aim_mpmsg_section_t)); sec->charset = charset; sec->charsubset = charsubset; @@ -1296,15 +1381,14 @@ return 0; } -faim_export int aim_mpmsg_addraw(OscarSession *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const gchar *data, guint16 datalen) +int aim_mpmsg_addraw(OscarData *od, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const gchar *data, guint16 datalen) { gchar *dup; - if (!(dup = malloc(datalen))) - return -1; + dup = malloc(datalen); memcpy(dup, data, datalen); - if (mpmsg_addsection(sess, mpm, charset, charsubset, dup, datalen) == -1) { + if (mpmsg_addsection(od, mpm, charset, charsubset, dup, datalen) == -1) { free(dup); return -1; } @@ -1313,14 +1397,14 @@ } /* XXX - should provide a way of saying ISO-8859-1 specifically */ -faim_export int aim_mpmsg_addascii(OscarSession *sess, aim_mpmsg_t *mpm, const char *ascii) +int aim_mpmsg_addascii(OscarData *od, aim_mpmsg_t *mpm, const char *ascii) { gchar *dup; if (!(dup = strdup(ascii))) return -1; - if (mpmsg_addsection(sess, mpm, 0x0000, 0x0000, dup, strlen(ascii)) == -1) { + if (mpmsg_addsection(od, mpm, 0x0000, 0x0000, dup, strlen(ascii)) == -1) { free(dup); return -1; } @@ -1328,22 +1412,21 @@ return 0; } -faim_export int aim_mpmsg_addunicode(OscarSession *sess, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen) +int aim_mpmsg_addunicode(OscarData *od, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen) { gchar *buf; ByteStream bs; int i; - if (!(buf = malloc(unicodelen * 2))) - return -1; - - aim_bstream_init(&bs, (guchar *)buf, unicodelen * 2); + buf = malloc(unicodelen * 2); + + byte_stream_init(&bs, (guchar *)buf, unicodelen * 2); /* We assume unicode is in /host/ byte order -- convert to network */ for (i = 0; i < unicodelen; i++) - aimbs_put16(&bs, unicode[i]); - - if (mpmsg_addsection(sess, mpm, 0x0002, 0x0000, buf, aim_bstream_curpos(&bs)) == -1) { + byte_stream_put16(&bs, unicode[i]); + + if (mpmsg_addsection(od, mpm, 0x0002, 0x0000, buf, byte_stream_curpos(&bs)) == -1) { free(buf); return -1; } @@ -1351,7 +1434,7 @@ return 0; } -faim_export void aim_mpmsg_free(OscarSession *sess, aim_mpmsg_t *mpm) +void aim_mpmsg_free(OscarData *od, aim_mpmsg_t *mpm) { aim_mpmsg_section_t *cur; @@ -1374,9 +1457,8 @@ * Start by building the multipart structures, then pick the first * human-readable section and stuff it into args->msg so no one gets * suspicious. - * */ -static int incomingim_ch1_parsemsgs(OscarSession *sess, aim_userinfo_t *userinfo, guint8 *data, int len, struct aim_incomingim_ch1_args *args) +static int incomingim_ch1_parsemsgs(OscarData *od, aim_userinfo_t *userinfo, guint8 *data, int len, struct aim_incomingim_ch1_args *args) { /* Should this be ASCII -> UNICODE -> Custom */ static const guint16 charsetpri[] = { @@ -1389,26 +1471,26 @@ ByteStream mbs; aim_mpmsg_section_t *sec; - aim_bstream_init(&mbs, data, len); - - while (aim_bstream_empty(&mbs)) { + byte_stream_init(&mbs, data, len); + + while (byte_stream_empty(&mbs)) { guint16 msglen, flag1, flag2; gchar *msgbuf; - aimbs_get8(&mbs); /* 01 */ - aimbs_get8(&mbs); /* 01 */ + byte_stream_get8(&mbs); /* 01 */ + byte_stream_get8(&mbs); /* 01 */ /* Message string length, including character set info. */ - msglen = aimbs_get16(&mbs); - if (msglen > aim_bstream_empty(&mbs)) + msglen = byte_stream_get16(&mbs); + if (msglen > byte_stream_empty(&mbs)) { gaim_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.", userinfo->sn); break; } /* Character set info */ - flag1 = aimbs_get16(&mbs); - flag2 = aimbs_get16(&mbs); + flag1 = byte_stream_get16(&mbs); + flag2 = byte_stream_get16(&mbs); /* Message. */ msglen -= 4; @@ -1426,8 +1508,8 @@ * the received messages are given in network byte order. * */ - msgbuf = (gchar *)aimbs_getraw(&mbs, msglen); - mpmsg_addsection(sess, &args->mpmsg, flag1, flag2, msgbuf, msglen); + msgbuf = (gchar *)byte_stream_getraw(&mbs, msglen); + mpmsg_addsection(od, &args->mpmsg, flag1, flag2, msgbuf, msglen); } /* while */ @@ -1486,7 +1568,7 @@ return 0; } -static int incomingim_ch1(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, ByteStream *bs, guint8 *cookie) +static int incomingim_ch1(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, ByteStream *bs, guint8 *cookie) { guint16 type, length; aim_rxcallback_t userfunc; @@ -1496,25 +1578,25 @@ memset(&args, 0, sizeof(args)); - aim_mpmsg_init(sess, &args.mpmsg); + aim_mpmsg_init(od, &args.mpmsg); /* * This used to be done using tlvchains. For performance reasons, * I've changed it to process the TLVs in-place. This avoids lots * of per-IM memory allocations. */ - while (aim_bstream_empty(bs)) + while (byte_stream_empty(bs)) { - type = aimbs_get16(bs); - length = aimbs_get16(bs); - - if (length > aim_bstream_empty(bs)) + type = byte_stream_get16(bs); + length = byte_stream_get16(bs); + + if (length > byte_stream_empty(bs)) { gaim_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->sn); break; } - endpos = aim_bstream_curpos(bs) + length; + endpos = byte_stream_curpos(bs) + length; if (type == 0x0002) { /* Message Block */ @@ -1527,11 +1609,11 @@ * */ - aimbs_get8(bs); /* 05 */ - aimbs_get8(bs); /* 01 */ - - args.featureslen = aimbs_get16(bs); - if (args.featureslen > aim_bstream_empty(bs)) + byte_stream_get8(bs); /* 05 */ + byte_stream_get8(bs); /* 01 */ + + args.featureslen = byte_stream_get16(bs); + if (args.featureslen > byte_stream_empty(bs)) { gaim_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->sn); break; @@ -1542,7 +1624,7 @@ } else { - args.features = aimbs_getraw(bs, args.featureslen); + args.features = byte_stream_getraw(bs, args.featureslen); args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES; } @@ -1550,7 +1632,7 @@ * The rest of the TLV contains one or more message * blocks... */ - incomingim_ch1_parsemsgs(sess, userinfo, bs->data + bs->offset /* XXX evil!!! */, length - 2 - 2 - args.featureslen, &args); + incomingim_ch1_parsemsgs(od, userinfo, bs->data + bs->offset /* XXX evil!!! */, length - 2 - 2 - args.featureslen, &args); } else if (type == 0x0003) { /* Server Ack Requested */ @@ -1567,10 +1649,10 @@ } else if (type == 0x0008) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */ - args.iconlen = aimbs_get32(bs); - aimbs_get16(bs); /* 0x0001 */ - args.iconsum = aimbs_get16(bs); - args.iconstamp = aimbs_get32(bs); + args.iconlen = byte_stream_get32(bs); + byte_stream_get16(bs); /* 0x0001 */ + args.iconsum = byte_stream_get16(bs); + args.iconstamp = byte_stream_get32(bs); /* * This looks to be a client bug. MacAIM 4.3 will @@ -1597,7 +1679,7 @@ free(args.extdata); args.extdatalen = length; - if (args.extdatalen > aim_bstream_empty(bs)) + if (args.extdatalen > byte_stream_empty(bs)) { gaim_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->sn); break; @@ -1605,7 +1687,7 @@ if (args.extdatalen == 0) args.extdata = NULL; else - args.extdata = aimbs_getraw(bs, args.extdatalen); + args.extdata = byte_stream_getraw(bs, args.extdatalen); } else { gaim_debug_misc("oscar", "incomingim_ch1: unknown TLV 0x%04x (len %d)\n", type, length); @@ -1619,21 +1701,21 @@ * TLV when the loop continues. * */ - aim_bstream_setpos(bs, endpos); + byte_stream_setpos(bs, endpos); } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); - - aim_mpmsg_free(sess, &args.mpmsg); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, channel, userinfo, &args); + + aim_mpmsg_free(od, &args.mpmsg); free(args.features); free(args.extdata); return ret; } -static void incomingim_ch2_buddylist(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, ByteStream *servdata) +static void incomingim_ch2_buddylist(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata) { /* @@ -1655,21 +1737,21 @@ * ... * ... */ - while (servdata && aim_bstream_empty(servdata)) { + while (servdata && byte_stream_empty(servdata)) { guint16 gnlen, numb; int i; char *gn; - gnlen = aimbs_get16(servdata); - gn = aimbs_getstr(servdata, gnlen); - numb = aimbs_get16(servdata); + gnlen = byte_stream_get16(servdata); + gn = byte_stream_getstr(servdata, gnlen); + numb = byte_stream_get16(servdata); for (i = 0; i < numb; i++) { guint16 bnlen; char *bn; - bnlen = aimbs_get16(servdata); - bn = aimbs_getstr(servdata, bnlen); + bnlen = byte_stream_get16(servdata); + bn = byte_stream_getstr(servdata, bnlen); gaim_debug_misc("oscar", "got a buddy list from %s: group %s, buddy %s\n", userinfo->sn, gn, bn); @@ -1682,7 +1764,7 @@ return; } -static void incomingim_ch2_buddyicon_free(OscarSession *sess, struct aim_incomingim_ch2_args *args) +static void incomingim_ch2_buddyicon_free(OscarData *od, IcbmArgsCh2 *args) { free(args->info.icon.icon); @@ -1690,14 +1772,14 @@ return; } -static void incomingim_ch2_buddyicon(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, ByteStream *servdata) +static void incomingim_ch2_buddyicon(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata) { if (servdata) { - args->info.icon.checksum = aimbs_get32(servdata); - args->info.icon.length = aimbs_get32(servdata); - args->info.icon.timestamp = aimbs_get32(servdata); - args->info.icon.icon = aimbs_getraw(servdata, args->info.icon.length); + args->info.icon.checksum = byte_stream_get32(servdata); + args->info.icon.length = byte_stream_get32(servdata); + args->info.icon.timestamp = byte_stream_get32(servdata); + args->info.icon.icon = byte_stream_getraw(servdata, args->info.icon.length); } args->destructor = (void *)incomingim_ch2_buddyicon_free; @@ -1705,7 +1787,7 @@ return; } -static void incomingim_ch2_chat_free(OscarSession *sess, struct aim_incomingim_ch2_args *args) +static void incomingim_ch2_chat_free(OscarData *od, IcbmArgsCh2 *args) { /* XXX - aim_chat_roominfo_free() */ @@ -1714,7 +1796,7 @@ return; } -static void incomingim_ch2_chat(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, ByteStream *servdata) +static void incomingim_ch2_chat(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata) { /* @@ -1728,7 +1810,7 @@ return; } -static void incomingim_ch2_icqserverrelay_free(OscarSession *sess, struct aim_incomingim_ch2_args *args) +static void incomingim_ch2_icqserverrelay_free(OscarData *od, IcbmArgsCh2 *args) { free((char *)args->info.rtfmsg.rtfmsg); @@ -1737,48 +1819,48 @@ } /* - * The relationship between AIM_CAPS_ICQSERVERRELAY and AIM_CAPS_ICQRTF is + * The relationship between OSCAR_CAPABILITY_ICQSERVERRELAY and OSCAR_CAPABILITY_ICQRTF is * kind of odd. This sends the client ICQRTF since that is all that I've seen * SERVERRELAY used for. * * Note that this is all little-endian. Cringe. * */ -static void incomingim_ch2_icqserverrelay(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, ByteStream *servdata) +static void incomingim_ch2_icqserverrelay(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata) { guint16 hdrlen, anslen, msglen; - hdrlen = aimbs_getle16(servdata); - aim_bstream_advance(servdata, hdrlen); - - hdrlen = aimbs_getle16(servdata); - aim_bstream_advance(servdata, hdrlen); - - args->info.rtfmsg.msgtype = aimbs_getle16(servdata); - - anslen = aimbs_getle32(servdata); - aim_bstream_advance(servdata, anslen); - - msglen = aimbs_getle16(servdata); - args->info.rtfmsg.rtfmsg = aimbs_getstr(servdata, msglen); - - args->info.rtfmsg.fgcolor = aimbs_getle32(servdata); - args->info.rtfmsg.bgcolor = aimbs_getle32(servdata); - - hdrlen = aimbs_getle32(servdata); - aim_bstream_advance(servdata, hdrlen); + hdrlen = byte_stream_getle16(servdata); + byte_stream_advance(servdata, hdrlen); + + hdrlen = byte_stream_getle16(servdata); + byte_stream_advance(servdata, hdrlen); + + args->info.rtfmsg.msgtype = byte_stream_getle16(servdata); + + anslen = byte_stream_getle32(servdata); + byte_stream_advance(servdata, anslen); + + msglen = byte_stream_getle16(servdata); + args->info.rtfmsg.rtfmsg = byte_stream_getstr(servdata, msglen); + + args->info.rtfmsg.fgcolor = byte_stream_getle32(servdata); + args->info.rtfmsg.bgcolor = byte_stream_getle32(servdata); + + hdrlen = byte_stream_getle32(servdata); + byte_stream_advance(servdata, hdrlen); args->destructor = (void *)incomingim_ch2_icqserverrelay_free; return; } -static void incomingim_ch2_sendfile_free(OscarSession *sess, struct aim_incomingim_ch2_args *args) +static void incomingim_ch2_sendfile_free(OscarData *od, IcbmArgsCh2 *args) { free(args->info.sendfile.filename); } -static void incomingim_ch2_sendfile(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, ByteStream *servdata) +static void incomingim_ch2_sendfile(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata) { args->destructor = (void *)incomingim_ch2_sendfile_free; @@ -1789,9 +1871,9 @@ int flen; /* subtype is one of AIM_OFT_SUBTYPE_* */ - args->info.sendfile.subtype = aimbs_get16(servdata); - args->info.sendfile.totfiles = aimbs_get16(servdata); - args->info.sendfile.totsize = aimbs_get32(servdata); + args->info.sendfile.subtype = byte_stream_get16(servdata); + args->info.sendfile.totfiles = byte_stream_get16(servdata); + args->info.sendfile.totsize = byte_stream_get32(servdata); /* * I hope to God I'm right when I guess that there is a @@ -1799,12 +1881,12 @@ * OFT tends to do that. Gotta love inconsistency. I saw * a 26 byte filename? */ - /* AAA - create an aimbs_getnullstr function (don't anymore)(maybe) */ + /* AAA - create an byte_stream_getnullstr function (don't anymore)(maybe) */ /* Use an inelegant way of getting the null-terminated filename, * since there's no easy bstream routine. */ - for (flen = 0; aimbs_get8(servdata); flen++); - aim_bstream_advance(servdata, -flen -1); - args->info.sendfile.filename = aimbs_getstr(servdata, flen); + for (flen = 0; byte_stream_get8(servdata); flen++); + byte_stream_advance(servdata, -flen -1); + args->info.sendfile.filename = byte_stream_getstr(servdata, flen); /* There is sometimes more after the null-terminated filename, * but I'm unsure of its format. */ @@ -1817,14 +1899,14 @@ return; } -typedef void (*ch2_args_destructor_t)(OscarSession *sess, struct aim_incomingim_ch2_args *args); - -static int incomingim_ch2(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie) +typedef void (*ch2_args_destructor_t)(OscarData *od, IcbmArgsCh2 *args); + +static int incomingim_ch2(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie) { aim_rxcallback_t userfunc; aim_tlv_t *block1, *servdatatlv; aim_tlvlist_t *list2; - struct aim_incomingim_ch2_args args; + IcbmArgsCh2 args; ByteStream bbs, sdbs, *sdbsptr = NULL; guint8 *cookie2; int ret = 0; @@ -1839,19 +1921,20 @@ * There's another block of TLVs embedded in the type 5 here. */ block1 = aim_tlv_gettlv(tlvlist, 0x0005, 1); - aim_bstream_init(&bbs, block1->value, block1->length); + byte_stream_init(&bbs, block1->value, block1->length); /* * First two bytes represent the status of the connection. + * One of the AIM_RENDEZVOUS_ defines. * * 0 is a request, 1 is a cancel, 2 is an accept */ - args.status = aimbs_get16(&bbs); + args.status = byte_stream_get16(&bbs); /* * Next comes the cookie. Should match the ICBM cookie. */ - cookie2 = aimbs_getraw(&bbs, 8); + cookie2 = byte_stream_getraw(&bbs, 8); if (memcmp(cookie, cookie2, 8) != 0) gaim_debug_misc("oscar", "rend: warning cookies don't match!\n"); memcpy(args.cookie, cookie2, 8); @@ -1861,7 +1944,7 @@ * The next 16bytes are a capability block so we can * identify what type of rendezvous this is. */ - args.reqclass = aim_locate_getcaps(sess, &bbs, 0x10); + args.type = aim_locate_getcaps(od, &bbs, 0x10); /* * What follows may be TLVs or nothing, depending on the @@ -1874,7 +1957,7 @@ /* * IP address to proxy the file transfer through. * - * XXX - I don't like this. Maybe just read in an int? Or inet_ntoa... + * TODO: I don't like this. Maybe just read in an int? Or inet_ntoa... */ if (aim_tlv_gettlv(list2, 0x0002, 1)) { aim_tlv_t *iptlv; @@ -1921,23 +2004,17 @@ args.port = aim_tlv_get16(list2, 0x0005, 1); /* - * Something to do with ft? -- two bytes - * 0x0001 - "I want to send you this file" - * 0x0002 - "I will accept this file from you" - * 0x0002 - Also used in ICQ Lite Beta 4.0 URLs + * File transfer "request number": + * 0x0001 - Initial file transfer request for no proxy or stage 1 proxy + * 0x0002 - "Reply request" for a stage 2 proxy (receiver wants to use proxy) + * 0x0003 - A third request has been sent; applies only to stage 3 proxied transfers */ - /* - * This is what I call the request number of the file transfer - * 0x0001 - Initial file transfer request for no proxy or stage 1 proxy - * 0x0002 - "Reply request" for a stage 2 proxy (receiver wants to use proxy) - * 0x0003 - A third request has been sent; applies only to stage 3 proxied transfers - * -- Jonathan - */ if (aim_tlv_gettlv(list2, 0x000a, 1)) - args.info.sendfile.reqnum = aim_tlv_get16(list2, 0x000a, 1); + args.requestnumber = aim_tlv_get16(list2, 0x000a, 1); /* - * Error code. + * Terminate connection/error code. 0x0001 means the other user + * canceled the connection. */ if (aim_tlv_gettlv(list2, 0x000b, 1)) args.errorcode = aim_tlv_get16(list2, 0x000b, 1); @@ -1980,9 +2057,7 @@ * Flag meaning we should proxy the file transfer through an AIM server */ if (aim_tlv_gettlv(list2, 0x0010, 1)) - args.info.sendfile.use_proxy = TRUE; - else - args.info.sendfile.use_proxy = FALSE; + args.use_proxy = TRUE; if (strlen(proxyip)) args.proxyip = (char *)proxyip; @@ -1994,13 +2069,13 @@ /* * This must be present in PROPOSALs, but will probably not * exist in CANCELs and ACCEPTs. Also exists in ICQ Lite - * Beta 4.0 URLs (AIM_CAPS_ICQSERVERRELAY). + * Beta 4.0 URLs (OSCAR_CAPABILITY_ICQSERVERRELAY). * * Service Data blocks are module-specific in format. */ if ((servdatatlv = aim_tlv_gettlv(list2, 0x2711 /* 10001 */, 1))) { - aim_bstream_init(&sdbs, servdatatlv->value, servdatatlv->length); + byte_stream_init(&sdbs, servdatatlv->value, servdatatlv->length); sdbsptr = &sdbs; } @@ -2009,23 +2084,23 @@ * * Not all of them have special handling (yet). */ - if (args.reqclass & AIM_CAPS_BUDDYICON) - incomingim_ch2_buddyicon(sess, mod, rx, snac, userinfo, &args, sdbsptr); - else if (args.reqclass & AIM_CAPS_SENDBUDDYLIST) - incomingim_ch2_buddylist(sess, mod, rx, snac, userinfo, &args, sdbsptr); - else if (args.reqclass & AIM_CAPS_CHAT) - incomingim_ch2_chat(sess, mod, rx, snac, userinfo, &args, sdbsptr); - else if (args.reqclass & AIM_CAPS_ICQSERVERRELAY) - incomingim_ch2_icqserverrelay(sess, mod, rx, snac, userinfo, &args, sdbsptr); - else if (args.reqclass & AIM_CAPS_SENDFILE) - incomingim_ch2_sendfile(sess, mod, rx, snac, userinfo, &args, sdbsptr); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); + if (args.type & OSCAR_CAPABILITY_BUDDYICON) + incomingim_ch2_buddyicon(od, conn, mod, frame, snac, userinfo, &args, sdbsptr); + else if (args.type & OSCAR_CAPABILITY_SENDBUDDYLIST) + incomingim_ch2_buddylist(od, conn, mod, frame, snac, userinfo, &args, sdbsptr); + else if (args.type & OSCAR_CAPABILITY_CHAT) + incomingim_ch2_chat(od, conn, mod, frame, snac, userinfo, &args, sdbsptr); + else if (args.type & OSCAR_CAPABILITY_ICQSERVERRELAY) + incomingim_ch2_icqserverrelay(od, conn, mod, frame, snac, userinfo, &args, sdbsptr); + else if (args.type & OSCAR_CAPABILITY_SENDFILE) + incomingim_ch2_sendfile(od, conn, mod, frame, snac, userinfo, &args, sdbsptr); + + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, channel, userinfo, &args); if (args.destructor) - ((ch2_args_destructor_t)args.destructor)(sess, &args); + ((ch2_args_destructor_t)args.destructor)(od, &args); free((char *)args.msg); free((char *)args.encoding); @@ -2036,7 +2111,7 @@ return ret; } -static int incomingim_ch4(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie) +static int incomingim_ch4(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie) { ByteStream meat; aim_rxcallback_t userfunc; @@ -2049,16 +2124,16 @@ */ if (!(block = aim_tlv_gettlv(tlvlist, 0x0005, 1))) return -1; - aim_bstream_init(&meat, block->value, block->length); - - args.uin = aimbs_getle32(&meat); - args.type = aimbs_getle8(&meat); - args.flags = aimbs_getle8(&meat); - args.msglen = aimbs_getle16(&meat); - args.msg = (gchar *)aimbs_getraw(&meat, args.msglen); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, userinfo, &args); + byte_stream_init(&meat, block->value, block->length); + + args.uin = byte_stream_getle32(&meat); + args.type = byte_stream_getle8(&meat); + args.flags = byte_stream_getle8(&meat); + args.msglen = byte_stream_getle16(&meat); + args.msg = (gchar *)byte_stream_getraw(&meat, args.msglen); + + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, channel, userinfo, &args); free(args.msg); @@ -2078,7 +2153,7 @@ * I have access to. Its not fast, its not clean. But it works. * */ -static int incomingim(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int incomingim(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; guchar *cookie; @@ -2090,7 +2165,7 @@ /* * Read ICBM Cookie. */ - cookie = aimbs_getraw(bs, 8); + cookie = byte_stream_getraw(bs, 8); /* * Channel ID. @@ -2108,7 +2183,7 @@ * possibly any system notice. * */ - channel = aimbs_get16(bs); + channel = byte_stream_get16(bs); /* * Extract the standard user info block. @@ -2125,7 +2200,7 @@ * never be two TLVs of the same type in one block. * */ - aim_info_extract(sess, bs, &userinfo); + aim_info_extract(od, bs, &userinfo); /* * From here on, its depends on what channel we're on. @@ -2136,7 +2211,7 @@ */ if (channel == 1) { - ret = incomingim_ch1(sess, mod, rx, snac, channel, &userinfo, bs, cookie); + ret = incomingim_ch1(od, conn, mod, frame, snac, channel, &userinfo, bs, cookie); } else if (channel == 2) { aim_tlvlist_t *tlvlist; @@ -2147,7 +2222,7 @@ */ tlvlist = aim_tlvlist_read(bs); - ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie); + ret = incomingim_ch2(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie); aim_tlvlist_free(&tlvlist); @@ -2155,7 +2230,7 @@ aim_tlvlist_t *tlvlist; tlvlist = aim_tlvlist_read(bs); - ret = incomingim_ch4(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie); + ret = incomingim_ch4(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie); aim_tlvlist_free(&tlvlist); } else { @@ -2177,46 +2252,45 @@ * returns -1 on error (couldn't alloc packet), 0 on success. * */ -faim_export int aim_im_warn(OscarSession *sess, OscarConnection *conn, const char *sn, guint32 flags) +int aim_im_warn(OscarData *od, FlapConnection *conn, const char *sn, guint32 flags) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !conn || !sn) + if (!od || !conn || !sn) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(sn)+13))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, sn, strlen(sn)+1); - aim_putsnac(&fr->data, 0x0004, 0x0008, 0x0000, snacid); - - aimbs_put16(&fr->data, (flags & AIM_WARN_ANON) ? 0x0001 : 0x0000); - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); - - aim_tx_enqueue(sess, fr); + frame = flap_frame_new(od, 0x02, strlen(sn)+13); + + snacid = aim_cachesnac(od, 0x0004, 0x0008, 0x0000, sn, strlen(sn)+1); + aim_putsnac(&frame->data, 0x0004, 0x0008, 0x0000, snacid); + + byte_stream_put16(&frame->data, (flags & AIM_WARN_ANON) ? 0x0001 : 0x0000); + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); + + flap_connection_send(conn, frame); return 0; } /* Subtype 0x000a */ -static int missedcall(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int missedcall(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; guint16 channel, nummissed, reason; aim_userinfo_t userinfo; - while (aim_bstream_empty(bs)) { - - channel = aimbs_get16(bs); - aim_info_extract(sess, bs, &userinfo); - nummissed = aimbs_get16(bs); - reason = aimbs_get16(bs); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); + while (byte_stream_empty(bs)) { + + channel = byte_stream_get16(bs); + aim_info_extract(od, bs, &userinfo); + nummissed = byte_stream_get16(bs); + reason = byte_stream_get16(bs); + + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, channel, &userinfo, nummissed, reason); aim_info_free(&userinfo); } @@ -2233,44 +2307,42 @@ * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers" * */ -faim_export int aim_im_denytransfer(OscarSession *sess, const char *sender, const guchar *cookie, guint16 code) +int aim_im_denytransfer(OscarData *od, const char *sn, const guchar *cookie, guint16 code) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sender)+6))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x000b, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x000b, 0x0000, snacid); - - aimbs_putraw(&fr->data, cookie, 8); - - aimbs_put16(&fr->data, 0x0002); /* channel */ - aimbs_put8(&fr->data, strlen(sender)); - aimbs_putstr(&fr->data, sender); + frame = flap_frame_new(od, 0x02, 10+8+2+1+strlen(sn)+6); + + snacid = aim_cachesnac(od, 0x0004, 0x000b, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x000b, 0x0000, snacid); + + byte_stream_putraw(&frame->data, cookie, 8); + + byte_stream_put16(&frame->data, 0x0002); /* channel */ + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); aim_tlvlist_add_16(&tl, 0x0003, code); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } /* - * Subtype 0x000b - Receive the response from an ICQ status message request. - * - * This contains the ICQ status message. Go figure. - * + * Subtype 0x000b - Receive the response from an ICQ status message + * request (in which case this contains the ICQ status message) or + * a file transfer or direct IM request was declined. */ -static int clientautoresp(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int clientautoresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -2279,17 +2351,17 @@ guchar *cookie; guint8 snlen; - cookie = aimbs_getraw(bs, 8); - channel = aimbs_get16(bs); - snlen = aimbs_get8(bs); - sn = aimbs_getstr(bs, snlen); - reason = aimbs_get16(bs); + cookie = byte_stream_getraw(bs, 8); + channel = byte_stream_get16(bs); + snlen = byte_stream_get8(bs); + sn = byte_stream_getstr(bs, snlen); + reason = byte_stream_get16(bs); if (channel == 0x0002) { /* File transfer declined */ - aimbs_get16(bs); /* Unknown */ - aimbs_get16(bs); /* Unknown */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, sn, reason, cookie); + byte_stream_get16(bs); /* Unknown */ + byte_stream_get16(bs); /* Unknown */ + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, channel, sn, reason, cookie); } else if (channel == 0x0004) { /* ICQ message */ switch (reason) { case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */ @@ -2297,13 +2369,13 @@ guint16 len; guint32 state; - len = aimbs_getle16(bs); /* Should be 0x001b */ - aim_bstream_advance(bs, len); /* Unknown */ - - len = aimbs_getle16(bs); /* Should be 0x000e */ - aim_bstream_advance(bs, len); /* Unknown */ - - statusmsgtype = aimbs_getle8(bs); + len = byte_stream_getle16(bs); /* Should be 0x001b */ + byte_stream_advance(bs, len); /* Unknown */ + + len = byte_stream_getle16(bs); /* Should be 0x000e */ + byte_stream_advance(bs, len); /* Unknown */ + + statusmsgtype = byte_stream_getle8(bs); switch (statusmsgtype) { case 0xe8: state = AIM_ICQ_STATE_AWAY; @@ -2325,22 +2397,22 @@ break; } - aimbs_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */ - aimbs_getle16(bs); /* Unknown - 0x0000 */ - aimbs_getle16(bs); /* Unknown - 0x0000 */ - - len = aimbs_getle16(bs); - msg = aimbs_getraw(bs, len); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, sn, reason, state, msg); + byte_stream_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */ + byte_stream_getle16(bs); /* Unknown - 0x0000 */ + byte_stream_getle16(bs); /* Unknown - 0x0000 */ + + len = byte_stream_getle16(bs); + msg = byte_stream_getraw(bs, len); + + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, channel, sn, reason, state, msg); free(msg); } break; default: { - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, sn, reason); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, channel, sn, reason); } break; } /* end switch */ } @@ -2359,7 +2431,7 @@ * sent. * */ -static int msgack(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int msgack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_rxcallback_t userfunc; guint16 ch; @@ -2367,12 +2439,12 @@ char *sn; int ret = 0; - cookie = aimbs_getraw(bs, 8); - ch = aimbs_get16(bs); - sn = aimbs_getstr(bs, aimbs_get8(bs)); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, ch, sn); + cookie = byte_stream_getraw(bs, 8); + ch = byte_stream_get16(bs); + sn = byte_stream_getstr(bs, byte_stream_get8(bs)); + + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, ch, sn); free(sn); free(cookie); @@ -2387,50 +2459,49 @@ * and Gaim 0.60 and newer. * */ -faim_export int aim_im_sendmtn(OscarSession *sess, guint16 type1, const char *sn, guint16 type2) +int aim_im_sendmtn(OscarData *od, guint16 type1, const char *sn, guint16 type2) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0002))) return -EINVAL; if (!sn) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+11+strlen(sn)+2))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x0014, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x0014, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 10+11+strlen(sn)+2); + + snacid = aim_cachesnac(od, 0x0004, 0x0014, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0004, 0x0014, 0x0000, snacid); /* * 8 days of light * Er, that is to say, 8 bytes of 0's */ - aimbs_put16(&fr->data, 0x0000); - aimbs_put16(&fr->data, 0x0000); - aimbs_put16(&fr->data, 0x0000); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); /* * Type 1 (should be 0x0001 for mtn) */ - aimbs_put16(&fr->data, type1); + byte_stream_put16(&frame->data, type1); /* * Dest sn */ - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); /* * Type 2 (should be 0x0000, 0x0001, or 0x0002 for mtn) */ - aimbs_put16(&fr->data, type2); - - aim_tx_enqueue(sess, fr); + byte_stream_put16(&frame->data, type2); + + flap_connection_send(conn, frame); return 0; } @@ -2442,7 +2513,7 @@ * and Gaim 0.60 and newer. * */ -static int mtn_receive(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int mtn_receive(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -2450,44 +2521,44 @@ guint8 snlen; guint16 type1, type2; - aim_bstream_advance(bs, 8); /* Unknown - All 0's */ - type1 = aimbs_get16(bs); - snlen = aimbs_get8(bs); - sn = aimbs_getstr(bs, snlen); - type2 = aimbs_get16(bs); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, type1, sn, type2); + byte_stream_advance(bs, 8); /* Unknown - All 0's */ + type1 = byte_stream_get16(bs); + snlen = byte_stream_get8(bs); + sn = byte_stream_getstr(bs, snlen); + type2 = byte_stream_get16(bs); + + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, type1, sn, type2); free(sn); return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0005) - return aim_im_paraminfo(sess, mod, rx, snac, bs); + return aim_im_paraminfo(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0006) - return outgoingim(sess, mod, rx, snac, bs); + return outgoingim(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0007) - return incomingim(sess, mod, rx, snac, bs); + return incomingim(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000a) - return missedcall(sess, mod, rx, snac, bs); + return missedcall(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000b) - return clientautoresp(sess, mod, rx, snac, bs); + return clientautoresp(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000c) - return msgack(sess, mod, rx, snac, bs); + return msgack(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0014) - return mtn_receive(sess, mod, rx, snac, bs); + return mtn_receive(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int msg_modfirst(OscarSession *sess, aim_module_t *mod) +int +msg_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0004; mod->version = 0x0001; mod->toolid = 0x0110;
--- a/src/protocols/oscar/family_icq.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_icq.c Fri Apr 07 05:10:56 2006 +0000 @@ -25,108 +25,105 @@ #include "oscar.h" -faim_export int aim_icq_reqofflinemsgs(OscarSession *sess) +int aim_icq_reqofflinemsgs(OscarData *od) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int bslen; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0015))) return -EINVAL; bslen = 2 + 4 + 2 + 2; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + bslen); - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid); /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x003c); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ + byte_stream_putle16(&frame->data, bslen - 2); + byte_stream_putle32(&frame->data, atoi(od->sn)); + byte_stream_putle16(&frame->data, 0x003c); /* I command thee. */ + byte_stream_putle16(&frame->data, snacid); /* eh. */ - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -faim_export int aim_icq_ackofflinemsgs(OscarSession *sess) +int aim_icq_ackofflinemsgs(OscarData *od) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int bslen; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0015))) return -EINVAL; bslen = 2 + 4 + 2 + 2; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + bslen); - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid); /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x003e); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ + byte_stream_putle16(&frame->data, bslen - 2); + byte_stream_putle32(&frame->data, atoi(od->sn)); + byte_stream_putle16(&frame->data, 0x003e); /* I command thee. */ + byte_stream_putle16(&frame->data, snacid); /* eh. */ - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -faim_export int -aim_icq_setsecurity(OscarSession *sess, gboolean auth_required, gboolean webaware) +int +aim_icq_setsecurity(OscarData *od, gboolean auth_required, gboolean webaware) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int bslen; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0015))) return -EINVAL; bslen = 2+4+2+2+2+2+2+1+1+1+1+1+1; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + bslen); - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid); /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ - aimbs_putle16(&fr->data, 0x0c3a); /* shrug. */ - aimbs_putle16(&fr->data, 0x030c); - aimbs_putle16(&fr->data, 0x0001); - aimbs_putle8(&fr->data, webaware); - aimbs_putle8(&fr->data, 0xf8); - aimbs_putle8(&fr->data, 0x02); - aimbs_putle8(&fr->data, 0x01); - aimbs_putle8(&fr->data, 0x00); - aimbs_putle8(&fr->data, !auth_required); + byte_stream_putle16(&frame->data, bslen - 2); + byte_stream_putle32(&frame->data, atoi(od->sn)); + byte_stream_putle16(&frame->data, 0x07d0); /* I command thee. */ + byte_stream_putle16(&frame->data, snacid); /* eh. */ + byte_stream_putle16(&frame->data, 0x0c3a); /* shrug. */ + byte_stream_putle16(&frame->data, 0x030c); + byte_stream_putle16(&frame->data, 0x0001); + byte_stream_putle8(&frame->data, webaware); + byte_stream_putle8(&frame->data, 0xf8); + byte_stream_putle8(&frame->data, 0x02); + byte_stream_putle8(&frame->data, 0x01); + byte_stream_putle8(&frame->data, 0x00); + byte_stream_putle8(&frame->data, !auth_required); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -134,22 +131,22 @@ /** * Change your ICQ password. * - * @param sess The oscar session + * @param od The oscar session * @param passwd The new password. If this is longer than 8 characters it * will be truncated. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_icq_changepasswd(OscarSession *sess, const char *passwd) +int aim_icq_changepasswd(OscarData *od, const char *passwd) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int bslen, passwdlen; if (!passwd) return -EINVAL; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0015))) return -EINVAL; passwdlen = strlen(passwd); @@ -157,34 +154,33 @@ passwdlen = MAXICQPASSLEN; bslen = 2+4+2+2+2+2+passwdlen+1; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + bslen); - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid); /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ - aimbs_putle16(&fr->data, 0x042e); /* shrug. */ - aimbs_putle16(&fr->data, passwdlen+1); - aimbs_putstr(&fr->data, passwd); - aimbs_putle8(&fr->data, '\0'); + byte_stream_putle16(&frame->data, bslen - 2); + byte_stream_putle32(&frame->data, atoi(od->sn)); + byte_stream_putle16(&frame->data, 0x07d0); /* I command thee. */ + byte_stream_putle16(&frame->data, snacid); /* eh. */ + byte_stream_putle16(&frame->data, 0x042e); /* shrug. */ + byte_stream_putle16(&frame->data, passwdlen+1); + byte_stream_putstr(&frame->data, passwd); + byte_stream_putle8(&frame->data, '\0'); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -faim_export int aim_icq_getallinfo(OscarSession *sess, const char *uin) +int aim_icq_getallinfo(OscarData *od, const char *uin) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int bslen; struct aim_icq_info *info; @@ -192,44 +188,43 @@ if (!uin || uin[0] < '0' || uin[0] > '9') return -EINVAL; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0015))) return -EINVAL; bslen = 2 + 4 + 2 + 2 + 2 + 4; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + bslen); - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid); /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ - aimbs_putle16(&fr->data, 0x04b2); /* shrug. */ - aimbs_putle32(&fr->data, atoi(uin)); + byte_stream_putle16(&frame->data, bslen - 2); + byte_stream_putle32(&frame->data, atoi(od->sn)); + byte_stream_putle16(&frame->data, 0x07d0); /* I command thee. */ + byte_stream_putle16(&frame->data, snacid); /* eh. */ + byte_stream_putle16(&frame->data, 0x04b2); /* shrug. */ + byte_stream_putle32(&frame->data, atoi(uin)); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); /* Keep track of this request and the ICQ number and request ID */ info = (struct aim_icq_info *)calloc(1, sizeof(struct aim_icq_info)); info->reqid = snacid; info->uin = atoi(uin); - info->next = sess->icq_info; - sess->icq_info = info; + info->next = od->icq_info; + od->icq_info = info; return 0; } -faim_export int aim_icq_getalias(OscarSession *sess, const char *uin) +int aim_icq_getalias(OscarData *od, const char *uin) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int bslen; struct aim_icq_info *info; @@ -237,112 +232,109 @@ if (!uin || uin[0] < '0' || uin[0] > '9') return -EINVAL; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0015))) return -EINVAL; bslen = 2 + 4 + 2 + 2 + 2 + 4; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + bslen); - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid); /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ - aimbs_putle16(&fr->data, 0x04ba); /* shrug. */ - aimbs_putle32(&fr->data, atoi(uin)); + byte_stream_putle16(&frame->data, bslen - 2); + byte_stream_putle32(&frame->data, atoi(od->sn)); + byte_stream_putle16(&frame->data, 0x07d0); /* I command thee. */ + byte_stream_putle16(&frame->data, snacid); /* eh. */ + byte_stream_putle16(&frame->data, 0x04ba); /* shrug. */ + byte_stream_putle32(&frame->data, atoi(uin)); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); /* Keep track of this request and the ICQ number and request ID */ info = (struct aim_icq_info *)calloc(1, sizeof(struct aim_icq_info)); info->reqid = snacid; info->uin = atoi(uin); - info->next = sess->icq_info; - sess->icq_info = info; + info->next = od->icq_info; + od->icq_info = info; return 0; } -faim_export int aim_icq_getsimpleinfo(OscarSession *sess, const char *uin) +int aim_icq_getsimpleinfo(OscarData *od, const char *uin) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int bslen; if (!uin || uin[0] < '0' || uin[0] > '9') return -EINVAL; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0015))) return -EINVAL; bslen = 2 + 4 + 2 + 2 + 2 + 4; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + bslen); - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid); /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ - aimbs_putle16(&fr->data, 0x051f); /* shrug. */ - aimbs_putle32(&fr->data, atoi(uin)); + byte_stream_putle16(&frame->data, bslen - 2); + byte_stream_putle32(&frame->data, atoi(od->sn)); + byte_stream_putle16(&frame->data, 0x07d0); /* I command thee. */ + byte_stream_putle16(&frame->data, snacid); /* eh. */ + byte_stream_putle16(&frame->data, 0x051f); /* shrug. */ + byte_stream_putle32(&frame->data, atoi(uin)); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } #if 0 -faim_export int aim_icq_sendxmlreq(OscarSession *sess, const char *xml) +int aim_icq_sendxmlreq(OscarData *od, const char *xml) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int bslen; if (!xml || !strlen(xml)) return -EINVAL; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0015))) return -EINVAL; bslen = 2 + 10 + 2 + strlen(xml) + 1; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + bslen); - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid); /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ - aimbs_putle16(&fr->data, 0x0998); /* shrug. */ - aimbs_putle16(&fr->data, strlen(xml) + 1); - aimbs_putraw(&fr->data, (guint8 *)xml, strlen(xml) + 1); + byte_stream_putle16(&frame->data, bslen - 2); + byte_stream_putle32(&frame->data, atoi(od->sn)); + byte_stream_putle16(&frame->data, 0x07d0); /* I command thee. */ + byte_stream_putle16(&frame->data, snacid); /* eh. */ + byte_stream_putle16(&frame->data, 0x0998); /* shrug. */ + byte_stream_putle16(&frame->data, strlen(xml) + 1); + byte_stream_putraw(&frame->data, (guint8 *)xml, strlen(xml) + 1); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -367,10 +359,10 @@ * Yeah hi Peter, whaaaat's happening. If there's any way to use * a codepage other than 1252 that would be great. Thaaaanks. */ -faim_export int aim_icq_sendsms(OscarSession *sess, const char *name, const char *msg, const char *alias) +int aim_icq_sendsms(OscarData *od, const char *name, const char *msg, const char *alias) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; int bslen, xmllen; char *xml; @@ -378,7 +370,7 @@ time_t t; struct tm *tm; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0015))) return -EINVAL; if (!name || !msg || !alias) @@ -389,10 +381,9 @@ timestr = gaim_utf8_strftime("%a, %d %b %Y %T %Z", tm); /* The length of xml included the null terminating character */ - xmllen = 225 + strlen(name) + strlen(msg) + strlen(sess->sn) + strlen(alias) + strlen(timestr) + 1; + xmllen = 225 + strlen(name) + strlen(msg) + strlen(od->sn) + strlen(alias) + strlen(timestr) + 1; - if (!(xml = (char *)malloc(xmllen*sizeof(char)))) - return -ENOMEM; + xml = g_new(char, xmllen); snprintf(xml, xmllen, "<icq_sms_message>\n" "\t<destination>%s</destination>\n" "\t<text>%s</text>\n" @@ -402,41 +393,38 @@ "\t<delivery_receipt>Yes</delivery_receipt>\n" "\t<time>%s</time>\n" "</icq_sms_message>\n", - name, msg, sess->sn, alias, timestr); + name, msg, od->sn, alias, timestr); bslen = 37 + xmllen; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) { - free(xml); - return -ENOMEM; - } + frame = flap_frame_new(od, 0x02, 10 + 4 + bslen); - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid); /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ + byte_stream_putle16(&frame->data, bslen - 2); + byte_stream_putle32(&frame->data, atoi(od->sn)); + byte_stream_putle16(&frame->data, 0x07d0); /* I command thee. */ + byte_stream_putle16(&frame->data, snacid); /* eh. */ /* From libicq200-0.3.2/src/SNAC-SRV.cpp */ - aimbs_putle16(&fr->data, 0x8214); - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, 0x0016); - aimbs_put32(&fr->data, 0x00000000); - aimbs_put32(&fr->data, 0x00000000); - aimbs_put32(&fr->data, 0x00000000); - aimbs_put32(&fr->data, 0x00000000); + byte_stream_putle16(&frame->data, 0x8214); + byte_stream_put16(&frame->data, 0x0001); + byte_stream_put16(&frame->data, 0x0016); + byte_stream_put32(&frame->data, 0x00000000); + byte_stream_put32(&frame->data, 0x00000000); + byte_stream_put32(&frame->data, 0x00000000); + byte_stream_put32(&frame->data, 0x00000000); - aimbs_put16(&fr->data, 0x0000); - aimbs_put16(&fr->data, xmllen); - aimbs_putstr(&fr->data, xml); + byte_stream_put16(&frame->data, 0x0000); + byte_stream_put16(&frame->data, xmllen); + byte_stream_putstr(&frame->data, xml); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); free(xml); @@ -482,7 +470,8 @@ /** * Subtype 0x0003 - Response to 0x0015/0x002, contains an ICQesque packet. */ -static int icqresponse(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +icqresponse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_tlvlist_t *tl; @@ -497,12 +486,12 @@ return 0; } - aim_bstream_init(&qbs, datatlv->value, datatlv->length); + byte_stream_init(&qbs, datatlv->value, datatlv->length); - cmdlen = aimbs_getle16(&qbs); - ouruin = aimbs_getle32(&qbs); - cmd = aimbs_getle16(&qbs); - reqid = aimbs_getle16(&qbs); + cmdlen = byte_stream_getle16(&qbs); + ouruin = byte_stream_getle32(&qbs); + cmd = byte_stream_getle16(&qbs); + reqid = byte_stream_getle16(&qbs); gaim_debug_misc("oscar", "icq response: %d bytes, %ld, 0x%04x, 0x%04x\n", cmdlen, ouruin, cmd, reqid); @@ -512,43 +501,43 @@ memset(&msg, 0, sizeof(msg)); - msg.sender = aimbs_getle32(&qbs); - msg.year = aimbs_getle16(&qbs); - msg.month = aimbs_getle8(&qbs); - msg.day = aimbs_getle8(&qbs); - msg.hour = aimbs_getle8(&qbs); - msg.minute = aimbs_getle8(&qbs); - msg.type = aimbs_getle8(&qbs); - msg.flags = aimbs_getle8(&qbs); - msg.msglen = aimbs_getle16(&qbs); - msg.msg = aimbs_getstr(&qbs, msg.msglen); + msg.sender = byte_stream_getle32(&qbs); + msg.year = byte_stream_getle16(&qbs); + msg.month = byte_stream_getle8(&qbs); + msg.day = byte_stream_getle8(&qbs); + msg.hour = byte_stream_getle8(&qbs); + msg.minute = byte_stream_getle8(&qbs); + msg.type = byte_stream_getle8(&qbs); + msg.flags = byte_stream_getle8(&qbs); + msg.msglen = byte_stream_getle16(&qbs); + msg.msg = byte_stream_getstr(&qbs, msg.msglen); - if ((userfunc = aim_callhandler(sess, rx->conn, OSCAR_FAMILY_ICQ, OSCAR_SUBTYPE_ICQ_OFFLINEMSG))) - ret = userfunc(sess, rx, &msg); + if ((userfunc = aim_callhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_OFFLINEMSG))) + ret = userfunc(od, conn, frame, &msg); free(msg.msg); } else if (cmd == 0x0042) { aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, OSCAR_FAMILY_ICQ, OSCAR_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE))) - ret = userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE))) + ret = userfunc(od, conn, frame); } else if (cmd == 0x07da) { /* information */ guint16 subtype; struct aim_icq_info *info; aim_rxcallback_t userfunc; - subtype = aimbs_getle16(&qbs); - aim_bstream_advance(&qbs, 1); /* 0x0a */ + subtype = byte_stream_getle16(&qbs); + byte_stream_advance(&qbs, 1); /* 0x0a */ /* find other data from the same request */ - for (info = sess->icq_info; info && (info->reqid != reqid); info = info->next); + for (info = od->icq_info; info && (info->reqid != reqid); info = info->next); if (!info) { info = (struct aim_icq_info *)calloc(1, sizeof(struct aim_icq_info)); info->reqid = reqid; - info->next = sess->icq_info; - sess->icq_info = info; + info->next = od->icq_info; + od->icq_info = info; } switch (subtype) { @@ -561,64 +550,64 @@ } break; case 0x00c8: { /* general and "home" information */ - info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homecity = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homestate = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homephone = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homefax = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homeaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->mobile = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homezip = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homecountry = aimbs_getle16(&qbs); + info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->email = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->homecity = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->homestate = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->homephone = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->homefax = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->homeaddr = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->mobile = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->homezip = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->homecountry = byte_stream_getle16(&qbs); /* 0x0a 00 02 00 */ /* 1 byte timezone? */ /* 1 byte hide email flag? */ } break; case 0x00dc: { /* personal information */ - info->age = aimbs_getle8(&qbs); - info->unknown = aimbs_getle8(&qbs); - info->gender = aimbs_getle8(&qbs); /* Not specified=0x00, Female=0x01, Male=0x02 */ - info->personalwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->birthyear = aimbs_getle16(&qbs); - info->birthmonth = aimbs_getle8(&qbs); - info->birthday = aimbs_getle8(&qbs); - info->language1 = aimbs_getle8(&qbs); - info->language2 = aimbs_getle8(&qbs); - info->language3 = aimbs_getle8(&qbs); + info->age = byte_stream_getle8(&qbs); + info->unknown = byte_stream_getle8(&qbs); + info->gender = byte_stream_getle8(&qbs); /* Not specified=0x00, Female=0x01, Male=0x02 */ + info->personalwebpage = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->birthyear = byte_stream_getle16(&qbs); + info->birthmonth = byte_stream_getle8(&qbs); + info->birthday = byte_stream_getle8(&qbs); + info->language1 = byte_stream_getle8(&qbs); + info->language2 = byte_stream_getle8(&qbs); + info->language3 = byte_stream_getle8(&qbs); /* 0x00 00 01 00 00 01 00 00 00 00 00 */ } break; case 0x00d2: { /* work information */ - info->workcity = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workstate = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workphone = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workfax = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workzip = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workcountry = aimbs_getle16(&qbs); - info->workcompany = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workdivision = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workposition = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - aim_bstream_advance(&qbs, 2); /* 0x01 00 */ - info->workwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workcity = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->workstate = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->workphone = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->workfax = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->workaddr = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->workzip = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->workcountry = byte_stream_getle16(&qbs); + info->workcompany = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->workdivision = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->workposition = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + byte_stream_advance(&qbs, 2); /* 0x01 00 */ + info->workwebpage = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); } break; case 0x00e6: { /* additional personal information */ - info->info = aimbs_getstr(&qbs, aimbs_getle16(&qbs)-1); + info->info = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)-1); } break; case 0x00eb: { /* email address(es) */ int i; - info->numaddresses = aimbs_getle16(&qbs); + info->numaddresses = byte_stream_getle16(&qbs); info->email2 = (char **)calloc(info->numaddresses, sizeof(char *)); for (i = 0; i < info->numaddresses; i++) { - info->email2[i] = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->email2[i] = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); if (i+1 != info->numaddresses) - aim_bstream_advance(&qbs, 1); /* 0x00 */ + byte_stream_advance(&qbs, 1); /* 0x00 */ } } break; @@ -629,10 +618,10 @@ } break; case 0x0104: { /* alias info */ - info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); /* email address? */ + info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + byte_stream_advance(&qbs, byte_stream_getle16(&qbs)); /* email address? */ /* Then 0x00 02 00 */ } break; @@ -641,30 +630,30 @@ } break; case 0x019a: { /* simple info */ - aim_bstream_advance(&qbs, 2); - info->uin = aimbs_getle32(&qbs); - info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + byte_stream_advance(&qbs, 2); + info->uin = byte_stream_getle32(&qbs); + info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); + info->email = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)); /* Then 0x00 02 00 00 00 00 00 */ } break; } /* End switch statement */ if (!(snac->flags & 0x0001)) { if (subtype != 0x0104) - if ((userfunc = aim_callhandler(sess, rx->conn, OSCAR_FAMILY_ICQ, OSCAR_SUBTYPE_ICQ_INFO))) - ret = userfunc(sess, rx, info); + if ((userfunc = aim_callhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_INFO))) + ret = userfunc(od, conn, frame, info); if (info->uin && info->nick) - if ((userfunc = aim_callhandler(sess, rx->conn, OSCAR_FAMILY_ICQ, OSCAR_SUBTYPE_ICQ_ALIAS))) - ret = userfunc(sess, rx, info); + if ((userfunc = aim_callhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_ALIAS))) + ret = userfunc(od, conn, frame, info); - if (sess->icq_info == info) { - sess->icq_info = info->next; + if (od->icq_info == info) { + od->icq_info = info->next; } else { struct aim_icq_info *cur; - for (cur=sess->icq_info; (cur->next && (cur->next!=info)); cur=cur->next); + for (cur=od->icq_info; (cur->next && (cur->next!=info)); cur=cur->next); if (cur->next) cur->next = cur->next->next; } @@ -677,31 +666,32 @@ return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0003) - return icqresponse(sess, mod, rx, snac, bs); + return icqresponse(od, conn, mod, frame, snac, bs); return 0; } -static void icq_shutdown(OscarSession *sess, aim_module_t *mod) +static void +icq_shutdown(OscarData *od, aim_module_t *mod) { struct aim_icq_info *del; - while (sess->icq_info) { - del = sess->icq_info; - sess->icq_info = sess->icq_info->next; + while (od->icq_info) { + del = od->icq_info; + od->icq_info = od->icq_info->next; aim_icq_freeinfo(del); } return; } -faim_internal int icq_modfirst(OscarSession *sess, aim_module_t *mod) +int +icq_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0015; mod->version = 0x0001; mod->toolid = 0x0110;
--- a/src/protocols/oscar/family_invite.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_invite.c Fri Apr 07 05:10:56 2006 +0000 @@ -38,7 +38,7 @@ #include "oscar.h" -faim_internal int invite_modfirst(OscarSession *sess, aim_module_t *mod) +int invite_modfirst(OscarData *od, aim_module_t *mod) { mod->family = 0x0006;
--- a/src/protocols/oscar/family_locate.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_locate.c Fri Apr 07 05:10:56 2006 +0000 @@ -51,37 +51,37 @@ */ /* - * Perhaps better called AIM_CAPS_SHORTCAPS + * Perhaps better called OSCAR_CAPABILITY_SHORTCAPS */ - {AIM_CAPS_ICHAT, + {OSCAR_CAPABILITY_ICHAT, {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_SECUREIM, + {OSCAR_CAPABILITY_SECUREIM, {0x09, 0x46, 0x00, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_VIDEO, + {OSCAR_CAPABILITY_VIDEO, {0x09, 0x46, 0x01, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* "Live Video" support in Windows AIM 5.5.3501 and newer */ - {AIM_CAPS_LIVEVIDEO, + {OSCAR_CAPABILITY_LIVEVIDEO, {0x09, 0x46, 0x01, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* "Camera" support in Windows AIM 5.5.3501 and newer */ - {AIM_CAPS_CAMERA, + {OSCAR_CAPABILITY_CAMERA, {0x09, 0x46, 0x01, 0x02, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* In Windows AIM 5.5.3501 and newer */ - {AIM_CAPS_GENERICUNKNOWN, + {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x09, 0x46, 0x01, 0x03, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* In iChatAV (version numbers...?) */ - {AIM_CAPS_ICHATAV, + {OSCAR_CAPABILITY_ICHATAV, {0x09, 0x46, 0x01, 0x05, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x45, 0x53, 0x54, 0x00}}, @@ -90,55 +90,55 @@ * 26 Sep 2003, Matthew Sachs suggested that, "this * is probably the capability for the SMS features." */ - {AIM_CAPS_SMS, + {OSCAR_CAPABILITY_SMS, {0x09, 0x46, 0x01, 0xff, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_GENERICUNKNOWN, + {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x09, 0x46, 0xf0, 0x03, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_GENERICUNKNOWN, + {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x09, 0x46, 0xf0, 0x04, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_GENERICUNKNOWN, + {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x09, 0x46, 0xf0, 0x05, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_HIPTOP, + {OSCAR_CAPABILITY_HIPTOP, {0x09, 0x46, 0x13, 0x23, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_TALK, + {OSCAR_CAPABILITY_TALK, {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_SENDFILE, + {OSCAR_CAPABILITY_SENDFILE, {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_ICQ_DIRECT, + {OSCAR_CAPABILITY_ICQ_DIRECT, {0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_DIRECTIM, + {OSCAR_CAPABILITY_DIRECTIM, {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_BUDDYICON, + {OSCAR_CAPABILITY_BUDDYICON, {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_ADDINS, + {OSCAR_CAPABILITY_ADDINS, {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_GETFILE, + {OSCAR_CAPABILITY_GETFILE, {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_ICQSERVERRELAY, + {OSCAR_CAPABILITY_ICQSERVERRELAY, {0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, @@ -148,14 +148,14 @@ * forgot to fix endianness, or they made a typo. It really doesn't * matter which. */ - {AIM_CAPS_GAMES, + {OSCAR_CAPABILITY_GAMES, {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_GAMES2, + {OSCAR_CAPABILITY_GAMES2, {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, 0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_SENDBUDDYLIST, + {OSCAR_CAPABILITY_SENDBUDDYLIST, {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, @@ -168,53 +168,53 @@ * see them as online (previous you could still see them, but they * couldn't see you. */ - {AIM_CAPS_INTEROPERATE, + {OSCAR_CAPABILITY_INTEROPERATE, {0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_ICQUTF8, + {OSCAR_CAPABILITY_ICQUTF8, {0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_ICQUTF8OLD, + {OSCAR_CAPABILITY_ICQUTF8OLD, {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8, 0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}}, /* * Chat is oddball. */ - {AIM_CAPS_CHAT, + {OSCAR_CAPABILITY_CHAT, {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* - {AIM_CAPS_ICQ2GO, + {OSCAR_CAPABILITY_ICQ2GO, {0x56, 0x3f, 0xc8, 0x09, 0x0b, 0x6f, 0x41, 0xbd, 0x9f, 0x79, 0x42, 0x26, 0x09, 0xdf, 0xa2, 0xf3}}, */ - {AIM_CAPS_ICQRTF, + {OSCAR_CAPABILITY_ICQRTF, {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}}, /* This is added by the servers and it only shows up for ourselves... */ - {AIM_CAPS_GENERICUNKNOWN, + {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09}}, - {AIM_CAPS_APINFO, + {OSCAR_CAPABILITY_APINFO, {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6, 0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}}, - {AIM_CAPS_TRILLIANCRYPT, + {OSCAR_CAPABILITY_TRILLIANCRYPT, {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb, 0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}}, - {AIM_CAPS_EMPTY, + {OSCAR_CAPABILITY_EMPTY, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {AIM_CAPS_LAST, + {OSCAR_CAPABILITY_LAST, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, }; @@ -225,18 +225,18 @@ * * @param userinfo Contains the new information for the buddy. */ -static void aim_locate_adduserinfo(OscarSession *sess, aim_userinfo_t *userinfo) { +static void aim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo) { aim_userinfo_t *cur; - OscarConnection *conn; + FlapConnection *conn; aim_rxcallback_t userfunc; - cur = aim_locate_finduserinfo(sess, userinfo->sn); + cur = aim_locate_finduserinfo(od, userinfo->sn); if (cur == NULL) { cur = (aim_userinfo_t *)calloc(1, sizeof(aim_userinfo_t)); cur->sn = strdup(userinfo->sn); - cur->next = sess->locate.userinfo; - sess->locate.userinfo = cur; + cur->next = od->locate.userinfo; + od->locate.userinfo = cur; } cur->warnlevel = userinfo->warnlevel; @@ -307,51 +307,65 @@ * messages in its buddy list, then it would need to know if a user's * away message changes. */ - conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE); - if ((userfunc = aim_callhandler(sess, conn, OSCAR_FAMILY_LOCATE, OSCAR_SUBTYPE_LOCATE_GOTINFOBLOCK))) - userfunc(sess, NULL, cur); + conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE); + if ((userfunc = aim_callhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK))) + userfunc(od, conn, NULL, cur); } -faim_export void aim_locate_dorequest(OscarSession *sess) { - struct userinfo_node *cur = sess->locate.torequest; +void aim_locate_dorequest(OscarData *od) { + struct userinfo_node *cur = od->locate.torequest; if (cur == NULL) return; - if (sess->locate.waiting_for_response == TRUE) + if (od->locate.waiting_for_response == TRUE) return; - sess->locate.waiting_for_response = TRUE; - aim_locate_getinfoshort(sess, cur->sn, 0x00000003); + od->locate.waiting_for_response = TRUE; + aim_locate_getinfoshort(od, cur->sn, 0x00000003); /* Move this node to the "requested" queue */ - sess->locate.torequest = cur->next; - cur->next = sess->locate.requested; - sess->locate.requested = cur; + od->locate.torequest = cur->next; + cur->next = od->locate.requested; + od->locate.requested = cur; +} + +static gboolean +gaim_reqinfo_timeout_cb(void *data) +{ + OscarData *od; + + od = data; + aim_locate_dorequest(od); + od->getinfotimer = 0; + + return FALSE; } /** * Remove this screen name from our queue. If this info was requested * by our info request queue, then pop the next element off of the queue. * - * @param sess The aim session. + * @param od The aim session. * @param sn Screen name of the info we just received. * @return True if the request was explicit (client requested the info), * false if the request was implicit (libfaim request the info). */ -static int aim_locate_gotuserinfo(OscarSession *sess, const char *sn) { +static int +aim_locate_gotuserinfo(OscarData *od, FlapConnection *conn, const char *sn) +{ struct userinfo_node *cur, *del; int was_explicit = TRUE; - while ((sess->locate.requested != NULL) && (aim_sncmp(sn, sess->locate.requested->sn) == 0)) { - del = sess->locate.requested; - sess->locate.requested = del->next; + while ((od->locate.requested != NULL) && (aim_sncmp(sn, od->locate.requested->sn) == 0)) { + del = od->locate.requested; + od->locate.requested = del->next; was_explicit = FALSE; free(del->sn); free(del); } - cur = sess->locate.requested; + cur = od->locate.requested; while ((cur != NULL) && (cur->next != NULL)) { if (aim_sncmp(sn, cur->next->sn) == 0) { del = cur->next; @@ -364,25 +378,26 @@ } if (!was_explicit) { - OscarConnection *conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE); - aim_rxcallback_t userfunc; - - sess->locate.waiting_for_response = FALSE; + od->locate.waiting_for_response = FALSE; - if ((userfunc = aim_callhandler(sess, conn, OSCAR_FAMILY_LOCATE, OSCAR_SUBTYPE_LOCATE_REQUESTINFOTIMEOUT))) - userfunc(sess, NULL); - else - aim_locate_dorequest(sess); + /* + * Wait a little while then call aim_locate_dorequest(od). + * This keeps us from hitting the rate limit due to + * requesting away messages and info too quickly. + */ + if (od->getinfotimer == 0) + od->getinfotimer = gaim_timeout_add(10000, + gaim_reqinfo_timeout_cb, od); } return was_explicit; } -faim_internal void aim_locate_requestuserinfo(OscarSession *sess, const char *sn) { +void aim_locate_requestuserinfo(OscarData *od, const char *sn) { struct userinfo_node *cur; /* Make sure we aren't already requesting info for this buddy */ - cur = sess->locate.torequest; + cur = od->locate.torequest; while (cur != NULL) { if (aim_sncmp(sn, cur->sn) == 0) return; @@ -392,20 +407,20 @@ /* Add a new node to our request queue */ cur = (struct userinfo_node *)malloc(sizeof(struct userinfo_node)); cur->sn = strdup(sn); - cur->next = sess->locate.torequest; - sess->locate.torequest = cur; + cur->next = od->locate.torequest; + od->locate.torequest = cur; /* Actually request some info up in this piece */ - aim_locate_dorequest(sess); + aim_locate_dorequest(od); } -faim_export aim_userinfo_t *aim_locate_finduserinfo(OscarSession *sess, const char *sn) { +aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *sn) { aim_userinfo_t *cur = NULL; if (sn == NULL) return NULL; - cur = sess->locate.userinfo; + cur = od->locate.userinfo; while (cur != NULL) { if (aim_sncmp(cur->sn, sn) == 0) @@ -416,18 +431,18 @@ return NULL; } -faim_internal guint32 aim_locate_getcaps(OscarSession *sess, ByteStream *bs, int len) +guint32 aim_locate_getcaps(OscarData *od, ByteStream *bs, int len) { guint32 flags = 0; int offset; - for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x10) { + for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x10) { guint8 *cap; int i, identified; - cap = aimbs_getraw(bs, 0x10); + cap = byte_stream_getraw(bs, 0x10); - for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) { + for (i = 0, identified = 0; !(aim_caps[i].flag & OSCAR_CAPABILITY_LAST); i++) { if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) { flags |= aim_caps[i].flag; identified++; @@ -450,18 +465,18 @@ return flags; } -faim_internal guint32 aim_locate_getcaps_short(OscarSession *sess, ByteStream *bs, int len) +guint32 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len) { guint32 flags = 0; int offset; - for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x02) { + for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x02) { guint8 *cap; int i, identified; - cap = aimbs_getraw(bs, 0x02); + cap = byte_stream_getraw(bs, 0x02); - for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) { + for (i = 0, identified = 0; !(aim_caps[i].flag & OSCAR_CAPABILITY_LAST); i++) { if (memcmp(&aim_caps[i].data[2], cap, 0x02) == 0) { flags |= aim_caps[i].flag; identified++; @@ -478,31 +493,33 @@ return flags; } -faim_internal int aimbs_putcaps(ByteStream *bs, guint32 caps) +int byte_stream_putcaps(ByteStream *bs, guint32 caps) { int i; if (!bs) return -EINVAL; - for (i = 0; aim_bstream_empty(bs); i++) { + for (i = 0; byte_stream_empty(bs); i++) { - if (aim_caps[i].flag == AIM_CAPS_LAST) + if (aim_caps[i].flag == OSCAR_CAPABILITY_LAST) break; if (caps & aim_caps[i].flag) - aimbs_putraw(bs, aim_caps[i].data, 0x10); + byte_stream_putraw(bs, aim_caps[i].data, 0x10); } return 0; } -static void dumptlv(OscarSession *sess, guint16 type, ByteStream *bs, guint8 len) +#if 0 +static void +dumptlv(OscarData *od, guint16 type, ByteStream *bs, guint8 len) { int i; - if (!sess || !bs || !len) + if (!od || !bs || !len) return; gaim_debug_misc("oscar", "userinfo: type =0x%04x\n", type); @@ -512,15 +529,16 @@ for (i = 0; i < len; i++) { if ((i % 8) == 0) gaim_debug_misc("oscar", "\nuserinfo: "); - gaim_debug_misc("oscar", "0x%2x ", aimbs_get8(bs)); + gaim_debug_misc("oscar", "0x%2x ", byte_stream_get8(bs)); } gaim_debug_misc("oscar", "\n"); return; } +#endif -faim_internal void aim_info_free(aim_userinfo_t *info) +void aim_info_free(aim_userinfo_t *info) { free(info->sn); free(info->iconcsum); @@ -536,7 +554,7 @@ * AIM is fairly regular about providing user info. This is a generic * routine to extract it in its standard form. */ -faim_internal int aim_info_extract(OscarSession *sess, ByteStream *bs, aim_userinfo_t *outinfo) +int aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *outinfo) { int curtlv, tlvcnt; guint8 snlen; @@ -551,19 +569,19 @@ * Screen name. Stored as an unterminated string prepended with a * byte containing its length. */ - snlen = aimbs_get8(bs); - outinfo->sn = aimbs_getstr(bs, snlen); + snlen = byte_stream_get8(bs); + outinfo->sn = byte_stream_getstr(bs, snlen); /* * Warning Level. Stored as an unsigned short. */ - outinfo->warnlevel = aimbs_get16(bs); + outinfo->warnlevel = byte_stream_get16(bs); /* * TLV Count. Unsigned short representing the number of * Type-Length-Value triples that follow. */ - tlvcnt = aimbs_get16(bs); + tlvcnt = byte_stream_get16(bs); /* * Parse out the Type-Length-Value triples as they're found. @@ -572,31 +590,31 @@ int endpos; guint16 type, length; - type = aimbs_get16(bs); - length = aimbs_get16(bs); + type = byte_stream_get16(bs); + length = byte_stream_get16(bs); - endpos = aim_bstream_curpos(bs) + length; + endpos = byte_stream_curpos(bs) + length; if (type == 0x0001) { /* * Type = 0x0001: User flags - * + * * Specified as any of the following ORed together: * 0x0001 Trial (user less than 60days) * 0x0002 Unknown bit 2 * 0x0004 AOL Main Service user * 0x0008 Unknown bit 4 - * 0x0010 Free (AIM) user + * 0x0010 Free (AIM) user * 0x0020 Away * 0x0400 ActiveBuddy * */ - outinfo->flags = aimbs_get16(bs); + outinfo->flags = byte_stream_get16(bs); outinfo->present |= AIM_USERINFO_PRESENT_FLAGS; } else if (type == 0x0002) { /* - * Type = 0x0002: Account creation time. + * Type = 0x0002: Account creation time. * * The time/date that the user originally registered for * the service, stored in time_t format. @@ -608,36 +626,36 @@ * since". All these years and I finally found out * that I got the name wrong. */ - outinfo->createtime = aimbs_get32(bs); + outinfo->createtime = byte_stream_get32(bs); outinfo->present |= AIM_USERINFO_PRESENT_CREATETIME; } else if (type == 0x0003) { /* * Type = 0x0003: On-Since date. * - * The time/date that the user started their current + * The time/date that the user started their current * session, stored in time_t format. */ - outinfo->onlinesince = aimbs_get32(bs); + outinfo->onlinesince = byte_stream_get32(bs); outinfo->present |= AIM_USERINFO_PRESENT_ONLINESINCE; } else if (type == 0x0004) { /* * Type = 0x0004: Idle time. * - * Number of minutes since the user actively used the + * Number of minutes since the user actively used the * service. * * Note that the client tells the server when to start - * counting idle times, so this may or may not be + * counting idle times, so this may or may not be * related to reality. */ - outinfo->idletime = aimbs_get16(bs); + outinfo->idletime = byte_stream_get16(bs); outinfo->present |= AIM_USERINFO_PRESENT_IDLE; } else if (type == 0x0005) { /* - * Type = 0x0005: Member since date. + * Type = 0x0005: Member since date. * * The time/date that the user originally registered for * the service, stored in time_t format. @@ -646,18 +664,18 @@ * creation time"), particularly in the self-info. * And particularly for ICQ? */ - outinfo->membersince = aimbs_get32(bs); + outinfo->membersince = byte_stream_get32(bs); outinfo->present |= AIM_USERINFO_PRESENT_MEMBERSINCE; } else if (type == 0x0006) { /* * Type = 0x0006: ICQ Online Status * - * ICQ's Away/DND/etc "enriched" status. Some decoding + * ICQ's Away/DND/etc "enriched" status. Some decoding * of values done by Scott <darkagl@pcnet.com> */ - aimbs_get16(bs); - outinfo->icqinfo.status = aimbs_get16(bs); + byte_stream_get16(bs); + outinfo->icqinfo.status = byte_stream_get16(bs); outinfo->present |= AIM_USERINFO_PRESENT_ICQEXTSTATUS; } else if (type == 0x0008) { @@ -674,11 +692,11 @@ * ICQ User IP Address. * Ahh, the joy of ICQ security. */ - outinfo->icqinfo.ipaddr = aimbs_get32(bs); + outinfo->icqinfo.ipaddr = byte_stream_get32(bs); outinfo->present |= AIM_USERINFO_PRESENT_ICQIPADDR; } else if (type == 0x000c) { - /* + /* * Type = 0x000c * * random crap containing the IP address, @@ -686,10 +704,10 @@ * * Format is: * 4 bytes - Our IP address, 0xc0 a8 01 2b for 192.168.1.43 - * + * * */ - aimbs_getrawbuf(bs, outinfo->icqinfo.crap, 0x25); + byte_stream_getrawbuf(bs, outinfo->icqinfo.crap, 0x25); outinfo->present |= AIM_USERINFO_PRESENT_ICQDATA; } else if (type == 0x000d) { @@ -699,7 +717,7 @@ * OSCAR Capability information. * */ - outinfo->capabilities |= aim_locate_getcaps(sess, bs, length); + outinfo->capabilities |= aim_locate_getcaps(od, bs, length); outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES; } else if (type == 0x000e) { @@ -715,31 +733,31 @@ * Type = 0x000f: Session Length. (AIM) * Type = 0x0010: Session Length. (AOL) * - * The duration, in seconds, of the user's current + * The duration, in seconds, of the user's current * session. * * Which TLV type this comes in depends on the * service the user is using (AIM or AOL). * */ - outinfo->sessionlen = aimbs_get32(bs); + outinfo->sessionlen = byte_stream_get32(bs); outinfo->present |= AIM_USERINFO_PRESENT_SESSIONLEN; } else if (type == 0x0019) { /* * Type = 0x0019 * - * OSCAR short capability information. A shortened + * OSCAR short capability information. A shortened * form of the normal capabilities. */ - outinfo->capabilities |= aim_locate_getcaps_short(sess, bs, length); + outinfo->capabilities |= aim_locate_getcaps_short(od, bs, length); outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES; } else if (type == 0x001b) { /* * Type = 0x001a * - * AOL short capability information. A shortened + * AOL short capability information. A shortened * form of the normal capabilities. */ @@ -770,42 +788,42 @@ */ int type2, number, length2; - while (aim_bstream_curpos(bs) < endpos) { - type2 = aimbs_get16(bs); - number = aimbs_get8(bs); - length2 = aimbs_get8(bs); + while (byte_stream_curpos(bs) < endpos) { + type2 = byte_stream_get16(bs); + number = byte_stream_get8(bs); + length2 = byte_stream_get8(bs); switch (type2) { case 0x0000: { /* This is an official buddy icon? */ /* This is always 5 bytes of "0x02 01 d2 04 72"? */ - aim_bstream_advance(bs, length2); + byte_stream_advance(bs, length2); } break; case 0x0001: { /* A buddy icon checksum */ if ((length2 > 0) && ((number == 0x00) || (number == 0x01))) { free(outinfo->iconcsum); outinfo->iconcsumtype = number; - outinfo->iconcsum = aimbs_getraw(bs, length2); + outinfo->iconcsum = byte_stream_getraw(bs, length2); outinfo->iconcsumlen = length2; } else - aim_bstream_advance(bs, length2); + byte_stream_advance(bs, length2); } break; case 0x0002: { /* A status/available message */ free(outinfo->status); free(outinfo->status_encoding); if (length2 >= 4) { - outinfo->status_len = aimbs_get16(bs); - outinfo->status = aimbs_getstr(bs, outinfo->status_len); - if (aimbs_get16(bs) == 0x0001) { /* We have an encoding */ - aimbs_get16(bs); - outinfo->status_encoding = aimbs_getstr(bs, aimbs_get16(bs)); + outinfo->status_len = byte_stream_get16(bs); + outinfo->status = byte_stream_getstr(bs, outinfo->status_len); + if (byte_stream_get16(bs) == 0x0001) { /* We have an encoding */ + byte_stream_get16(bs); + outinfo->status_encoding = byte_stream_getstr(bs, byte_stream_get16(bs)); } else { /* No explicit encoding, client should use UTF-8 */ outinfo->status_encoding = NULL; } } else { - aim_bstream_advance(bs, length2); + byte_stream_advance(bs, length2); outinfo->status_len = 0; outinfo->status = g_strdup(""); outinfo->status_encoding = NULL; @@ -813,7 +831,7 @@ } break; default: { - aim_bstream_advance(bs, length2); + byte_stream_advance(bs, length2); } break; } } @@ -837,23 +855,25 @@ /* * Reaching here indicates that either AOL has - * added yet another TLV for us to deal with, + * added yet another TLV for us to deal with, * or the parsing has gone Terribly Wrong. * * Either way, inform the owner and attempt * recovery. * */ +#if 0 gaim_debug_misc("oscar", "userinfo: **warning: unexpected TLV:\n"); gaim_debug_misc("oscar", "userinfo: sn =%s\n", outinfo->sn); - dumptlv(sess, type, bs, length); + dumptlv(od, type, bs, length); +#endif } /* Save ourselves. */ - aim_bstream_setpos(bs, endpos); + byte_stream_setpos(bs, endpos); } - aim_locate_adduserinfo(sess, outinfo); + aim_locate_adduserinfo(od, outinfo); return 0; } @@ -861,17 +881,18 @@ /* * Inverse of aim_info_extract() */ -faim_internal int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info) +int +aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info) { aim_tlvlist_t *tlvlist = NULL; if (!bs || !info) return -EINVAL; - aimbs_put8(bs, strlen(info->sn)); - aimbs_putstr(bs, info->sn); + byte_stream_put8(bs, strlen(info->sn)); + byte_stream_putstr(bs, info->sn); - aimbs_put16(bs, info->warnlevel); + byte_stream_put16(bs, info->warnlevel); if (info->present & AIM_USERINFO_PRESENT_FLAGS) aim_tlvlist_add_16(&tlvlist, 0x0001, info->flags); @@ -898,7 +919,7 @@ if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) aim_tlvlist_add_32(&tlvlist, (guint16)((info->flags & AIM_FLAG_AOL) ? 0x0010 : 0x000f), info->sessionlen); - aimbs_put16(bs, aim_tlvlist_count(&tlvlist)); + byte_stream_put16(bs, aim_tlvlist_count(&tlvlist)); aim_tlvlist_write(bs, &tlvlist); aim_tlvlist_free(&tlvlist); @@ -908,7 +929,8 @@ /* * Subtype 0x0001 */ -static int error(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -917,7 +939,7 @@ char *sn; int was_explicit; - if (!(snac2 = aim_remsnac(sess, snac->id))) { + if (!(snac2 = aim_remsnac(od, snac->id))) { gaim_debug_misc("oscar", "faim: locate.c, error(): received response from unknown request!\n"); return 0; } @@ -932,17 +954,17 @@ return 0; } - reason = aimbs_get16(bs); + reason = byte_stream_get16(bs); /* - * Remove this screen name from our queue. If the client requested - * this buddy's info explicitly, then notify them that we do not have + * Remove this screen name from our queue. If the client requested + * this buddy's info explicitly, then notify them that we do not have * info for this buddy. */ - was_explicit = aim_locate_gotuserinfo(sess, sn); + was_explicit = aim_locate_gotuserinfo(od, conn, sn); if (was_explicit == TRUE) - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, reason, sn); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, reason, sn); if (snac2) free(snac2->data); @@ -957,14 +979,15 @@ * Request Location services rights. * */ -faim_export int aim_locate_reqrights(OscarSession *sess) +int +aim_locate_reqrights(OscarData *od) { - OscarConnection *conn; + FlapConnection *conn; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE))) return -EINVAL; - return aim_genericreq_n_snacid(sess, conn, OSCAR_FAMILY_LOCATE, OSCAR_SUBTYPE_LOCATE_REQRIGHTS); + return aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_REQRIGHTS); } /* @@ -976,7 +999,8 @@ * t(0003) - short - unknown (value = 10) * t(0004) - short - unknown (value = 2048) [ICQ only?] */ -static int rights(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_tlvlist_t *tlvlist; aim_rxcallback_t userfunc; @@ -988,8 +1012,8 @@ if (aim_tlv_gettlv(tlvlist, 0x0001, 1)) maxsiglen = aim_tlv_get16(tlvlist, 0x0001, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, maxsiglen); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, maxsiglen); aim_tlvlist_free(&tlvlist); @@ -1016,18 +1040,19 @@ * obvious equivalent). * */ -faim_export int aim_locate_setprofile(OscarSession *sess, +int +aim_locate_setprofile(OscarData *od, const char *profile_encoding, const gchar *profile, const int profile_len, const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; char *encoding; static const char defencoding[] = {"text/aolrtf; charset=\"%s\""}; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE))) return -EINVAL; if (!profile && !awaymsg) @@ -1041,9 +1066,6 @@ if (profile) { /* no + 1 here because of %s */ encoding = malloc(strlen(defencoding) + strlen(profile_encoding)); - if (encoding == NULL) { - return -ENOMEM; - } snprintf(encoding, strlen(defencoding) + strlen(profile_encoding), defencoding, profile_encoding); aim_tlvlist_add_str(&tl, 0x0001, encoding); aim_tlvlist_add_raw(&tl, 0x0002, profile_len, (const guchar *)profile); @@ -1061,9 +1083,6 @@ if (awaymsg) { if (awaymsg_len) { encoding = malloc(strlen(defencoding) + strlen(awaymsg_encoding)); - if (encoding == NULL) { - return -ENOMEM; - } snprintf(encoding, strlen(defencoding) + strlen(awaymsg_encoding), defencoding, awaymsg_encoding); aim_tlvlist_add_str(&tl, 0x0003, encoding); aim_tlvlist_add_raw(&tl, 0x0004, awaymsg_len, (const guchar *)awaymsg); @@ -1072,16 +1091,15 @@ aim_tlvlist_add_noval(&tl, 0x0004); } - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_tlvlist_size(&tl)))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(&tl)); - snacid = aim_cachesnac(sess, 0x0002, 0x0004, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0002, 0x004, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0002, 0x0004, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0002, 0x004, 0x0000, snacid); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1089,28 +1107,28 @@ /* * Subtype 0x0004 - Set your client's capabilities. */ -faim_export int aim_locate_setcaps(OscarSession *sess, guint32 caps) +int +aim_locate_setcaps(OscarData *od, guint32 caps) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE))) return -EINVAL; aim_tlvlist_add_caps(&tl, 0x0005, caps); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_tlvlist_size(&tl)))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(&tl)); - snacid = aim_cachesnac(sess, 0x0002, 0x0004, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0002, 0x004, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0002, 0x0004, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0002, 0x004, 0x0000, snacid); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1124,32 +1142,33 @@ * 0x0003 - Away message * 0x0004 - Capabilities */ -faim_export int aim_locate_getinfo(OscarSession *sess, const char *sn, guint16 infotype) +int +aim_locate_getinfo(OscarData *od, const char *sn, guint16 infotype) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE)) || !sn) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)) || !sn) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 12+1+strlen(sn)))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 12+1+strlen(sn)); - snacid = aim_cachesnac(sess, 0x0002, 0x0005, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0002, 0x0005, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0002, 0x0005, 0x0000, snacid); - aimbs_put16(&fr->data, infotype); - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); + aim_putsnac(&frame->data, 0x0002, 0x0005, 0x0000, snacid); + byte_stream_put16(&frame->data, infotype); + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } /* Subtype 0x0006 */ -static int userinfo(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1159,7 +1178,7 @@ int was_explicit; userinfo = (aim_userinfo_t *)malloc(sizeof(aim_userinfo_t)); - aim_info_extract(sess, bs, userinfo); + aim_info_extract(od, bs, userinfo); tlvlist = aim_tlvlist_read(bs); /* Profile will be 1 and 2 */ @@ -1181,14 +1200,14 @@ /* Caps will be 5 */ if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) { ByteStream cbs; - aim_bstream_init(&cbs, tlv->value, tlv->length); - userinfo->capabilities = aim_locate_getcaps(sess, &cbs, tlv->length); + byte_stream_init(&cbs, tlv->value, tlv->length); + userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length); userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES; } aim_tlvlist_free(&tlvlist); - aim_locate_adduserinfo(sess, userinfo); - userinfo2 = aim_locate_finduserinfo(sess, userinfo->sn); + aim_locate_adduserinfo(od, userinfo); + userinfo2 = aim_locate_finduserinfo(od, userinfo->sn); aim_info_free(userinfo); free(userinfo); @@ -1197,10 +1216,10 @@ * this buddy's info explicitly, then notify them that we have info * for this buddy. */ - was_explicit = aim_locate_gotuserinfo(sess, userinfo2->sn); + was_explicit = aim_locate_gotuserinfo(od, conn, userinfo2->sn); if (was_explicit == TRUE) - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, userinfo2); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, userinfo2); return ret; } @@ -1212,14 +1231,14 @@ * privacy: 1 to allow searching, 0 to disallow. * */ -faim_export int aim_locate_setdirinfo(OscarSession *sess, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy) +int aim_locate_setdirinfo(OscarData *od, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE))) return -EINVAL; aim_tlvlist_add_16(&tl, 0x000a, privacy); @@ -1246,16 +1265,15 @@ if (street) aim_tlvlist_add_str(&tl, 0x0021, street); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl)))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl)); - snacid = aim_cachesnac(sess, 0x0002, 0x0009, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0002, 0x0009, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0002, 0x0009, 0x0000, snacid); - aim_tlvlist_write(&fr->data, &tl); + aim_putsnac(&frame->data, 0x0002, 0x0009, 0x0000, snacid); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1263,27 +1281,26 @@ /* * Subtype 0x000b - Huh? What is this? */ -faim_export int aim_locate_000b(OscarSession *sess, const char *sn) +int aim_locate_000b(OscarData *od, const char *sn) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; return -EINVAL; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE)) || !sn) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)) || !sn) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+1+strlen(sn)); - snacid = aim_cachesnac(sess, 0x0002, 0x000b, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0002, 0x000b, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0002, 0x000b, 0x0000, snacid); - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); + aim_putsnac(&frame->data, 0x0002, 0x000b, 0x0000, snacid); + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1294,14 +1311,14 @@ * XXX pass these in better * */ -faim_export int aim_locate_setinterests(OscarSession *sess, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy) +int aim_locate_setinterests(OscarData *od, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE))) return -EINVAL; /* ?? privacy ?? */ @@ -1318,16 +1335,15 @@ if (interest5) aim_tlvlist_add_str(&tl, 0x0000b, interest5); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl)))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl)); - snacid = aim_cachesnac(sess, 0x0002, 0x000f, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0002, 0x000f, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0002, 0x000f, 0x0000, 0); - aim_tlvlist_write(&fr->data, &tl); + aim_putsnac(&frame->data, 0x0002, 0x000f, 0x0000, 0); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1344,59 +1360,59 @@ * 0x00000008 - Certification. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_locate_getinfoshort(OscarSession *sess, const char *sn, guint32 flags) +int aim_locate_getinfoshort(OscarData *od, const char *sn, guint32 flags) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_LOCATE)) || !sn) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)) || !sn) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+1+strlen(sn)))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+4+1+strlen(sn)); - snacid = aim_cachesnac(sess, 0x0002, 0x0015, 0x0000, sn, strlen(sn)+1); + snacid = aim_cachesnac(od, 0x0002, 0x0015, 0x0000, sn, strlen(sn)+1); - aim_putsnac(&fr->data, 0x0002, 0x0015, 0x0000, snacid); - aimbs_put32(&fr->data, flags); - aimbs_put8(&fr->data, strlen(sn)); - aimbs_putstr(&fr->data, sn); + aim_putsnac(&frame->data, 0x0002, 0x0015, 0x0000, snacid); + byte_stream_put32(&frame->data, flags); + byte_stream_put8(&frame->data, strlen(sn)); + byte_stream_putstr(&frame->data, sn); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0001) - return error(sess, mod, rx, snac, bs); + return error(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0003) - return rights(sess, mod, rx, snac, bs); + return rights(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0006) - return userinfo(sess, mod, rx, snac, bs); + return userinfo(od, conn, mod, frame, snac, bs); return 0; } -static void locate_shutdown(OscarSession *sess, aim_module_t *mod) +static void +locate_shutdown(OscarData *od, aim_module_t *mod) { aim_userinfo_t *del; - while (sess->locate.userinfo) { - del = sess->locate.userinfo; - sess->locate.userinfo = sess->locate.userinfo->next; + while (od->locate.userinfo) { + del = od->locate.userinfo; + od->locate.userinfo = od->locate.userinfo->next; aim_info_free(del); free(del); } } -faim_internal int locate_modfirst(OscarSession *sess, aim_module_t *mod) +int +locate_modfirst(OscarData *od, aim_module_t *mod) { - - mod->family = OSCAR_FAMILY_LOCATE; + mod->family = SNAC_FAMILY_LOCATE; mod->version = 0x0001; mod->toolid = 0x0110; mod->toolversion = 0x0629;
--- a/src/protocols/oscar/family_odir.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_odir.c Fri Apr 07 05:10:56 2006 +0000 @@ -33,19 +33,19 @@ * * Search for an AIM screen name based on their email address. * - * @param sess The oscar session. + * @param od The oscar session. * @param region Should be "us-ascii" unless you know what you're doing. * @param email The email address you want to search for. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_odir_email(OscarSession *sess, const char *region, const char *email) +int aim_odir_email(OscarData *od, const char *region, const char *email) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x000f)) || !region || !email) + if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region || !email) return -EINVAL; /* Create a TLV chain, write it to the outgoing frame, then free the chain */ @@ -53,15 +53,14 @@ aim_tlvlist_add_16(&tl, 0x000a, 0x0001); /* Type of search */ aim_tlvlist_add_str(&tl, 0x0005, email); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl)))) - return -ENOMEM; - snacid = aim_cachesnac(sess, 0x000f, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x000f, 0x0002, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl)); + snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x000f, 0x0002, 0x0000, snacid); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -73,7 +72,7 @@ * Search for an AIM screen name based on various info * about the person. * - * @param sess The oscar session. + * @param od The oscar session. * @param region Should be "us-ascii" unless you know what you're doing. * @param first The first name of the person you want to search for. * @param middle The middle name of the person you want to search for. @@ -87,14 +86,14 @@ * @param address The street address where the person you want to seach for resides. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_odir_name(OscarSession *sess, const char *region, const char *first, const char *middle, const char *last, const char *maiden, const char *nick, const char *city, const char *state, const char *country, const char *zip, const char *address) +int aim_odir_name(OscarData *od, const char *region, const char *first, const char *middle, const char *last, const char *maiden, const char *nick, const char *city, const char *state, const char *country, const char *zip, const char *address) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x000f)) || !region) + if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region) return -EINVAL; /* Create a TLV chain, write it to the outgoing frame, then free the chain */ @@ -121,15 +120,14 @@ if (address) aim_tlvlist_add_str(&tl, 0x0021, address); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl)))) - return -ENOMEM; - snacid = aim_cachesnac(sess, 0x000f, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x000f, 0x0002, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl)); + snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x000f, 0x0002, 0x0000, snacid); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -138,18 +136,18 @@ /** * Subtype 0x0002 - Submit a User Search Request * - * @param sess The oscar session. + * @param od The oscar session. * @param interest1 An interest you want to search for. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_odir_interest(OscarSession *sess, const char *region, const char *interest) +int aim_odir_interest(OscarData *od, const char *region, const char *interest) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x000f)) || !region) + if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region) return -EINVAL; /* Create a TLV chain, write it to the outgoing frame, then free the chain */ @@ -158,15 +156,14 @@ if (interest) aim_tlvlist_add_str(&tl, 0x0001, interest); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_tlvlist_size(&tl)))) - return -ENOMEM; - snacid = aim_cachesnac(sess, 0x000f, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x000f, 0x0002, 0x0000, snacid); + frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl)); + snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x000f, 0x0002, 0x0000, snacid); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -176,23 +173,23 @@ * Subtype 0x0003 - Receive Reply From a User Search * */ -static int parseresults(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int parseresults(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; guint16 tmp, numresults; struct aim_odir *results = NULL; - tmp = aimbs_get16(bs); /* Unknown */ - tmp = aimbs_get16(bs); /* Unknown */ - aim_bstream_advance(bs, tmp); + tmp = byte_stream_get16(bs); /* Unknown */ + tmp = byte_stream_get16(bs); /* Unknown */ + byte_stream_advance(bs, tmp); - numresults = aimbs_get16(bs); /* Number of results to follow */ + numresults = byte_stream_get16(bs); /* Number of results to follow */ /* Allocate a linked list, 1 node per result */ while (numresults) { struct aim_odir *new; - aim_tlvlist_t *tl = aim_tlvlist_readnum(bs, aimbs_get16(bs)); + aim_tlvlist_t *tl = aim_tlvlist_readnum(bs, byte_stream_get16(bs)); new = (struct aim_odir *)malloc(sizeof(struct aim_odir)); new->first = aim_tlv_getstr(tl, 0x0001, 1); new->last = aim_tlv_getstr(tl, 0x0002, 1); @@ -213,8 +210,8 @@ numresults--; } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, results); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, results); /* Now free everything from above */ while (results) { @@ -240,18 +237,18 @@ return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0003) - return parseresults(sess, mod, rx, snac, bs); + return parseresults(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int odir_modfirst(OscarSession *sess, aim_module_t *mod) +int +odir_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x000f; mod->version = 0x0001; mod->toolid = 0x0010;
--- a/src/protocols/oscar/family_oservice.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_oservice.c Fri Apr 07 05:10:56 2006 +0000 @@ -28,21 +28,21 @@ #include "cipher.h" /* Subtype 0x0002 - Client Online */ -faim_export int aim_clientready(OscarSession *sess, OscarConnection *conn) +int +aim_clientready(OscarData *od, FlapConnection *conn) { aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; struct snacgroup *sg; - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; if (!ins) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 1152); - snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0001, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0001, 0x0002, 0x0000, snacid); /* * Send only the tool versions that the server cares about (that it @@ -51,16 +51,16 @@ for (sg = ins->groups; sg; sg = sg->next) { aim_module_t *mod; - if ((mod = aim__findmodulebygroup(sess, sg->group))) { - aimbs_put16(&fr->data, mod->family); - aimbs_put16(&fr->data, mod->version); - aimbs_put16(&fr->data, mod->toolid); - aimbs_put16(&fr->data, mod->toolversion); + if ((mod = aim__findmodulebygroup(od, sg->group))) { + byte_stream_put16(&frame->data, mod->family); + byte_stream_put16(&frame->data, mod->version); + byte_stream_put16(&frame->data, mod->toolid); + byte_stream_put16(&frame->data, mod->toolversion); } else gaim_debug_misc("oscar", "aim_clientready: server supports group 0x%04x but we don't!\n", sg->group); } - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -79,18 +79,18 @@ * shortly after the rate information is acknowledged. * */ -static int hostonline(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +hostonline(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { guint16 *families; int famcount; - if (!(families = malloc(aim_bstream_empty(bs)))) - return 0; + families = malloc(byte_stream_empty(bs)); - for (famcount = 0; aim_bstream_empty(bs); famcount++) { - families[famcount] = aimbs_get16(bs); - aim_conn_addgroup(rx->conn, families[famcount]); + for (famcount = 0; byte_stream_empty(bs); famcount++) { + families[famcount] = byte_stream_get16(bs); + flap_connection_addgroup(conn, families[famcount]); } free(families); @@ -104,60 +104,67 @@ * give it. * */ - aim_setversions(sess, rx->conn); + aim_setversions(od, conn); return 1; } /* Subtype 0x0004 - Service request */ -faim_export int aim_reqservice(OscarSession *sess, OscarConnection *conn, guint16 serviceid) +int aim_reqservice(OscarData *od, guint16 serviceid) { - return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid); + FlapConnection *conn; + + conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS); + + return aim_genericreq_s(od, conn, 0x0001, 0x0004, &serviceid); } /* - * Join a room of name roomname. This is the first step to joining an - * already created room. It's basically a Service Request for - * family 0x000e, with a little added on to specify the exchange and room + * Join a room of name roomname. This is the first step to joining an + * already created room. It's basically a Service Request for + * family 0x000e, with a little added on to specify the exchange and room * name. */ -faim_export int aim_chat_join(OscarSession *sess, OscarConnection *conn, guint16 exchange, const char *roomname, guint16 instance) +int +aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance) { - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; struct chatsnacinfo csi; - if (!sess || !conn || !roomname || !strlen(roomname)) + conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS); + if (!od || !conn || !roomname || !strlen(roomname)) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 512); memset(&csi, 0, sizeof(csi)); csi.exchange = exchange; strncpy(csi.name, roomname, sizeof(csi.name)); csi.instance = instance; - snacid = aim_cachesnac(sess, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi)); - aim_putsnac(&fr->data, 0x0001, 0x0004, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi)); + aim_putsnac(&frame->data, 0x0001, 0x0004, 0x0000, snacid); /* * Requesting service chat (0x000e) */ - aimbs_put16(&fr->data, 0x000e); + byte_stream_put16(&frame->data, 0x000e); aim_tlvlist_add_chatroom(&tl, 0x0001, exchange, roomname, instance); - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } /* Subtype 0x0005 - Redirect */ -static int redirect(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +redirect(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { struct aim_redirect_data redir; aim_rxcallback_t userfunc; @@ -182,9 +189,9 @@ redir.cookie = (guchar *)aim_tlv_getstr(tlvlist, 0x0006, 1); /* Fetch original SNAC so we can get csi if needed */ - origsnac = aim_remsnac(sess, snac->id); + origsnac = aim_remsnac(od, snac->id); - if ((redir.group == AIM_CONN_TYPE_CHAT) && origsnac) { + if ((redir.group == SNAC_FAMILY_CHAT) && origsnac) { struct chatsnacinfo *csi = (struct chatsnacinfo *)origsnac->data; redir.chat.exchange = csi->exchange; @@ -192,8 +199,8 @@ redir.chat.instance = csi->instance; } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, &redir); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, &redir); free((void *)redir.ip); free((void *)redir.cookie); @@ -208,9 +215,10 @@ } /* Subtype 0x0006 - Request Rate Information. */ -faim_internal int aim_reqrates(OscarSession *sess, OscarConnection *conn) +int +aim_reqrates(OscarData *od, FlapConnection *conn) { - return aim_genericreq_n_snacid(sess, conn, 0x0001, 0x0006); + return aim_genericreq_n_snacid(od, conn, 0x0001, 0x0006); } /* @@ -219,7 +227,7 @@ * level, etc), and a set of SNAC family/type pairs associated with * it. The rate classes, their limiting properties, and the definitions * of which SNACs are belong to which class, are defined in the - * Rate Response packet at login to each host. + * Rate Response packet at login to each host. * * Logically, all rate offenses within one class count against further * offenses for other SNACs in the same class (ie, sending messages @@ -233,10 +241,10 @@ * members as follows... * * Rate class 0x0001: - * - Everything thats not in any of the other classes + * - Everything thats not in any of the other classes * * Rate class 0x0002: - * - Buddy list add/remove + * - Buddy list add/remove * - Permit list add/remove * - Deny list add/remove * @@ -252,23 +260,21 @@ * - Outgoing chat ICBMs * * The only other thing of note is that class 5 (chat) has slightly looser - * limiting properties than class 3 (normal messages). But thats just a + * limiting properties than class 3 (normal messages). But thats just a * small bit of trivia for you. * * The last thing that needs to be learned about the rate limiting * system is how the actual numbers relate to the passing of time. This * seems to be a big mystery. - * + * */ -static void rc_addclass(struct rateclass **head, struct rateclass *inrc) +static void +rc_addclass(struct rateclass **head, struct rateclass *inrc) { struct rateclass *rc, *rc2; - if (!(rc = malloc(sizeof(struct rateclass)))) - return; - - memcpy(rc, inrc, sizeof(struct rateclass)); + rc = g_memdup(inrc, sizeof(struct rateclass)); rc->next = NULL; for (rc2 = *head; rc2 && rc2->next; rc2 = rc2->next) @@ -282,7 +288,8 @@ return; } -static struct rateclass *rc_findclass(struct rateclass **head, guint16 id) +static struct rateclass * +rc_findclass(struct rateclass **head, guint16 id) { struct rateclass *rc; @@ -294,14 +301,12 @@ return NULL; } -static void rc_addpair(struct rateclass *rc, guint16 group, guint16 type) +static void +rc_addpair(struct rateclass *rc, guint16 group, guint16 type) { struct snacpair *sp, *sp2; - if (!(sp = malloc(sizeof(struct snacpair)))) - return; - memset(sp, 0, sizeof(struct snacpair)); - + sp = g_new0(struct snacpair, 1); sp->group = group; sp->subtype = type; sp->next = NULL; @@ -318,9 +323,10 @@ } /* Subtype 0x0007 - Rate Parameters */ -static int rateresp(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +rateresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - aim_conn_inside_t *ins = (aim_conn_inside_t *)rx->conn->inside; + aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; guint16 numclasses, i; aim_rxcallback_t userfunc; @@ -328,32 +334,30 @@ /* * First are the parameters for each rate class. */ - numclasses = aimbs_get16(bs); + numclasses = byte_stream_get16(bs); for (i = 0; i < numclasses; i++) { struct rateclass rc; memset(&rc, 0, sizeof(struct rateclass)); - rc.classid = aimbs_get16(bs); - rc.windowsize = aimbs_get32(bs); - rc.clear = aimbs_get32(bs); - rc.alert = aimbs_get32(bs); - rc.limit = aimbs_get32(bs); - rc.disconnect = aimbs_get32(bs); - rc.current = aimbs_get32(bs); - rc.max = aimbs_get32(bs); + rc.classid = byte_stream_get16(bs); + rc.windowsize = byte_stream_get32(bs); + rc.clear = byte_stream_get32(bs); + rc.alert = byte_stream_get32(bs); + rc.limit = byte_stream_get32(bs); + rc.disconnect = byte_stream_get32(bs); + rc.current = byte_stream_get32(bs); + rc.max = byte_stream_get32(bs); /* * The server will send an extra five bytes of parameters * depending on the version we advertised in 1/17. If we * didn't send 1/17 (evil!), then this will crash and you - * die, as it will default to the old version but we have - * the new version hardcoded here. + * die, as it will default to the old version but we have + * the new version hardcoded here. */ if (mod->version >= 3) - aimbs_getrawbuf(bs, rc.unknown, sizeof(rc.unknown)); - - gaim_debug_misc("oscar", "--- Adding rate class %d to connection type %d: window size = %ld, clear = %ld, alert = %ld, limit = %ld, disconnect = %ld, current = %ld, max = %ld\n", rx->conn->type, rc.classid, rc.windowsize, rc.clear, rc.alert, rc.limit, rc.disconnect, rc.current, rc.max); + byte_stream_getrawbuf(bs, rc.unknown, sizeof(rc.unknown)); rc_addclass(&ins->rates, &rc); } @@ -366,16 +370,16 @@ struct rateclass *rc; int j; - classid = aimbs_get16(bs); - count = aimbs_get16(bs); + classid = byte_stream_get16(bs); + count = byte_stream_get16(bs); rc = rc_findclass(&ins->rates, classid); for (j = 0; j < count; j++) { guint16 group, subtype; - group = aimbs_get16(bs); - subtype = aimbs_get16(bs); + group = byte_stream_get16(bs); + subtype = byte_stream_get16(bs); if (rc) rc_addpair(rc, group, subtype); @@ -392,83 +396,84 @@ * Last step in the conn init procedure is to acknowledge that we * agree to these draconian limitations. */ - aim_rates_addparam(sess, rx->conn); + aim_rates_addparam(od, conn); /* * Finally, tell the client it's ready to go... */ - if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE))) - userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE))) + userfunc(od, conn, frame); return 1; } /* Subtype 0x0008 - Add Rate Parameter */ -faim_internal int aim_rates_addparam(OscarSession *sess, OscarConnection *conn) +int +aim_rates_addparam(OscarData *od, FlapConnection *conn) { aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; struct rateclass *rc; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 512); - snacid = aim_cachesnac(sess, 0x0001, 0x0008, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x0008, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0001, 0x0008, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0001, 0x0008, 0x0000, snacid); for (rc = ins->rates; rc; rc = rc->next) - aimbs_put16(&fr->data, rc->classid); + byte_stream_put16(&frame->data, rc->classid); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } /* Subtype 0x0009 - Delete Rate Parameter */ -faim_internal int aim_rates_delparam(OscarSession *sess, OscarConnection *conn) +int +aim_rates_delparam(OscarData *od, FlapConnection *conn) { aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; struct rateclass *rc; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 512); - snacid = aim_cachesnac(sess, 0x0001, 0x0009, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x0009, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0001, 0x0009, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0001, 0x0009, 0x0000, snacid); for (rc = ins->rates; rc; rc = rc->next) - aimbs_put16(&fr->data, rc->classid); + byte_stream_put16(&frame->data, rc->classid); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } /* Subtype 0x000a - Rate Change */ -static int ratechange(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +ratechange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; guint16 code, rateclass; guint32 currentavg, maxavg, windowsize, clear, alert, limit, disconnect; - code = aimbs_get16(bs); - rateclass = aimbs_get16(bs); + code = byte_stream_get16(bs); + rateclass = byte_stream_get16(bs); - windowsize = aimbs_get32(bs); - clear = aimbs_get32(bs); - alert = aimbs_get32(bs); - limit = aimbs_get32(bs); - disconnect = aimbs_get32(bs); - currentavg = aimbs_get32(bs); - maxavg = aimbs_get32(bs); + windowsize = byte_stream_get32(bs); + clear = byte_stream_get32(bs); + alert = byte_stream_get32(bs); + limit = byte_stream_get32(bs); + disconnect = byte_stream_get32(bs); + currentavg = byte_stream_get32(bs); + maxavg = byte_stream_get32(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); return ret; } @@ -476,10 +481,10 @@ /* * How Migrations work. * - * The server sends a Server Pause message, which the client should respond to - * with a Server Pause Ack, which contains the families it needs on this - * connection. The server will send a Migration Notice with an IP address, and - * then disconnect. Next the client should open the connection and send the + * The server sends a Server Pause message, which the client should respond to + * with a Server Pause Ack, which contains the families it needs on this + * connection. The server will send a Migration Notice with an IP address, and + * then disconnect. Next the client should open the connection and send the * cookie. Repeat the normal login process and pretend this never happened. * * The Server Pause contains no data. @@ -487,13 +492,14 @@ */ /* Subtype 0x000b - Service Pause */ -static int serverpause(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +serverpause(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame); return ret; } @@ -509,61 +515,64 @@ * libfaim can cause. * */ -faim_export int aim_sendpauseack(OscarSession *sess, OscarConnection *conn) +int +aim_sendpauseack(OscarData *od, FlapConnection *conn) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; struct snacgroup *sg; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1024))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 1024); - snacid = aim_cachesnac(sess, 0x0001, 0x000c, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x000c, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0001, 0x000c, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0001, 0x000c, 0x0000, snacid); /* - * This list should have all the groups that the original - * Host Online / Server Ready said this host supports. And + * This list should have all the groups that the original + * Host Online / Server Ready said this host supports. And * we want them all back after the migration. */ for (sg = ins->groups; sg; sg = sg->next) - aimbs_put16(&fr->data, sg->group); + byte_stream_put16(&frame->data, sg->group); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } /* Subtype 0x000d - Service Resume */ -static int serverresume(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +serverresume(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame); return ret; } /* Subtype 0x000e - Request self-info */ -faim_export int aim_reqpersonalinfo(OscarSession *sess, OscarConnection *conn) +int +aim_reqpersonalinfo(OscarData *od, FlapConnection *conn) { - return aim_genericreq_n_snacid(sess, conn, 0x0001, 0x000e); + return aim_genericreq_n_snacid(od, conn, 0x0001, 0x000e); } /* Subtype 0x000f - Self User Info */ -static int selfinfo(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +selfinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; aim_userinfo_t userinfo; - aim_info_extract(sess, bs, &userinfo); + aim_info_extract(od, bs, &userinfo); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, &userinfo); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, &userinfo); aim_info_free(&userinfo); @@ -571,7 +580,8 @@ } /* Subtype 0x0010 - Evil Notification */ -static int evilnotify(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +evilnotify(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -580,13 +590,13 @@ memset(&userinfo, 0, sizeof(aim_userinfo_t)); - newevil = aimbs_get16(bs); + newevil = byte_stream_get16(bs); - if (aim_bstream_empty(bs)) - aim_info_extract(sess, bs, &userinfo); + if (byte_stream_empty(bs)) + aim_info_extract(od, bs, &userinfo); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, newevil, &userinfo); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, newevil, &userinfo); aim_info_free(&userinfo); @@ -602,25 +612,27 @@ * call it again with zero when you're back. * */ -faim_export int aim_srv_setidle(OscarSession *sess, guint32 idletime) +int +aim_srv_setidle(OscarData *od, guint32 idletime) { - OscarConnection *conn; + FlapConnection *conn; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_BOS))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS))) return -EINVAL; - return aim_genericreq_l(sess, conn, 0x0001, 0x0011, &idletime); + return aim_genericreq_l(od, conn, 0x0001, 0x0011, &idletime); } /* * Subtype 0x0012 - Service Migrate * * This is the final SNAC sent on the original connection during a migration. - * It contains the IP and cookie used to connect to the new server, and + * It contains the IP and cookie used to connect to the new server, and * optionally a list of the SNAC groups being migrated. * */ -static int migrate(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +migrate(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_rxcallback_t userfunc; int ret = 0; @@ -634,17 +646,17 @@ * migration can actually be quite selective about what groups it * moves to the new server. When not all the groups for a connection * are migrated, or they are all migrated but some groups are moved - * to a different server than others, it is called a bifurcated + * to a different server than others, it is called a bifurcated * migration. * * Let's play dumb and not support that. * */ - groupcount = aimbs_get16(bs); + groupcount = byte_stream_get16(bs); for (i = 0; i < groupcount; i++) { guint16 group; - group = aimbs_get16(bs); + group = byte_stream_get16(bs); gaim_debug_misc("oscar", "bifurcated migration unsupported -- group 0x%04x\n", group); } @@ -656,8 +668,8 @@ cktlv = aim_tlv_gettlv(tl, 0x0006, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, ip, cktlv ? cktlv->value : NULL); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, ip, cktlv ? cktlv->value : NULL); aim_tlvlist_free(&tl); free(ip); @@ -666,7 +678,8 @@ } /* Subtype 0x0013 - Message of the Day */ -static int motd(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +motd(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_rxcallback_t userfunc; char *msg = NULL; @@ -682,20 +695,20 @@ * 2 Advisory upgrade * 3 System bulletin * 4 Nothing's wrong ("top o the world" -- normal) - * 5 Lets-break-something. + * 5 Lets-break-something. * */ - id = aimbs_get16(bs); + id = byte_stream_get16(bs); - /* - * TLVs follow + /* + * TLVs follow */ tlvlist = aim_tlvlist_read(bs); msg = aim_tlv_getstr(tlvlist, 0x000b, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, id, msg); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, id, msg); free(msg); @@ -704,7 +717,7 @@ return ret; } -/* +/* * Subtype 0x0014 - Set privacy flags * * Normally 0x03. @@ -713,93 +726,96 @@ * Bit 2: Allows other AIM users to see how long you've been a member. * */ -faim_export int aim_bos_setprivacyflags(OscarSession *sess, OscarConnection *conn, guint32 flags) +int +aim_bos_setprivacyflags(OscarData *od, FlapConnection *conn, guint32 flags) { - return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags); + return aim_genericreq_l(od, conn, 0x0001, 0x0014, &flags); } /* * Subtype 0x0016 - No-op * - * WinAIM sends these every 4min or so to keep the connection alive. Its not + * WinAIM sends these every 4min or so to keep the connection alive. Its not * really necessary. * - * Wha? No? Since when? I think WinAIM sends an empty channel 3 - * SNAC as a no-op... + * Wha? No? Since when? I think WinAIM sends an empty channel 5 + * FLAP as a no-op... */ -faim_export int aim_nop(OscarSession *sess, OscarConnection *conn) +int +aim_nop(OscarData *od, FlapConnection *conn) { - return aim_genericreq_n(sess, conn, 0x0001, 0x0016); + return aim_genericreq_n(od, conn, 0x0001, 0x0016); } -/* +/* * Subtype 0x0017 - Set client versions * - * If you've seen the clientonline/clientready SNAC you're probably + * If you've seen the clientonline/clientready SNAC you're probably * wondering what the point of this one is. And that point seems to be * that the versions in the client online SNAC are sent too late for the * server to be able to use them to change the protocol for the earlier - * login packets (client versions are sent right after Host Online is + * login packets (client versions are sent right after Host Online is * received, but client online versions aren't sent until quite a bit later). * We can see them already making use of this by changing the format of * the rate information based on what version of group 1 we advertise here. * */ -faim_internal int aim_setversions(OscarSession *sess, OscarConnection *conn) +int +aim_setversions(OscarData *od, FlapConnection *conn) { aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; struct snacgroup *sg; - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; if (!ins) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 1152); - snacid = aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x0017, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0001, 0x0017, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0001, 0x0017, 0x0000, snacid); /* * Send only the versions that the server cares about (that it - * marked as supporting in the server ready SNAC). + * marked as supporting in the server ready SNAC). */ for (sg = ins->groups; sg; sg = sg->next) { aim_module_t *mod; - if ((mod = aim__findmodulebygroup(sess, sg->group))) { - aimbs_put16(&fr->data, mod->family); - aimbs_put16(&fr->data, mod->version); + if ((mod = aim__findmodulebygroup(od, sg->group))) { + byte_stream_put16(&frame->data, mod->family); + byte_stream_put16(&frame->data, mod->version); } else gaim_debug_misc("oscar", "aim_setversions: server supports group 0x%04x but we don't!\n", sg->group); } - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } /* Subtype 0x0018 - Host versions */ -static int hostversions(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +hostversions(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int vercount; guint8 *versions; /* This is frivolous. (Thank you SmarterChild.) */ - vercount = aim_bstream_empty(bs)/4; - versions = aimbs_getraw(bs, aim_bstream_empty(bs)); + vercount = byte_stream_empty(bs)/4; + versions = byte_stream_getraw(bs, byte_stream_empty(bs)); free(versions); /* * Now request rates. */ - aim_reqrates(sess, rx->conn); + aim_reqrates(od, conn); return 1; } -/* +/* * Subtype 0x001e - Set various account settings (mostly ICQ related). * * These settings are transient, not server-stored (i.e. they only @@ -814,24 +830,24 @@ * These are the same TLVs seen in user info. You can * also set 0x0008 and 0x000c. */ -faim_export int aim_setextstatus(OscarSession *sess, guint32 status) +int +aim_setextstatus(OscarData *od, guint32 status) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; guint32 data; - if (!sess || !(conn = aim_conn_findbygroup(sess, OSCAR_FAMILY_ICBM))) + if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM))) return -EINVAL; data = AIM_ICQ_STATE_HIDEIP | AIM_ICQ_STATE_DIRECTREQUIREAUTH | status; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 8))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 8); - snacid = aim_cachesnac(sess, 0x0001, 0x001e, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid); aim_tlvlist_add_32(&tl, 0x0006, data); #if 0 @@ -839,10 +855,10 @@ aim_tlvlist_add_raw(&tl, 0x0011, 0x0005, unknown 0x01 61 10 f6 41); aim_tlvlist_add_16(&tl, 0x0012, unknown 0x00 00); #endif - aim_tlvlist_write(&fr->data, &tl); + aim_tlvlist_write(&frame->data, &tl); aim_tlvlist_free(&tl); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -856,46 +872,45 @@ * These are the same TLVs seen in user info. You can * also set 0x0008 and 0x000c. */ -faim_export int aim_srv_setstatusmsg(OscarSession *sess, const char *msg) +int +aim_srv_setstatusmsg(OscarData *od, const char *msg) { - OscarConnection *conn; - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!od || !(conn = flap_connection_findbygroup(od, 0x0004))) return -EINVAL; if ((msg != NULL) && *msg != '\0') { - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + strlen(msg) + 8))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + strlen(msg) + 8); - snacid = aim_cachesnac(sess, 0x0001, 0x001e, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid); - aimbs_put16(&fr->data, 0x001d); /* userinfo TLV type */ - aimbs_put16(&fr->data, strlen(msg)+8); /* total length of userinfo TLV data */ - aimbs_put16(&fr->data, 0x0002); - aimbs_put8(&fr->data, 0x04); - aimbs_put8(&fr->data, strlen(msg)+4); - aimbs_put16(&fr->data, strlen(msg)); - aimbs_putstr(&fr->data, msg); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x001d); /* userinfo TLV type */ + byte_stream_put16(&frame->data, strlen(msg)+8); /* total length of userinfo TLV data */ + byte_stream_put16(&frame->data, 0x0002); + byte_stream_put8(&frame->data, 0x04); + byte_stream_put8(&frame->data, strlen(msg)+4); + byte_stream_put16(&frame->data, strlen(msg)); + byte_stream_putstr(&frame->data, msg); + byte_stream_put16(&frame->data, 0x0000); } else { - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + 8))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10 + 4 + 8); - snacid = aim_cachesnac(sess, 0x0001, 0x001e, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid); + snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0); + aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid); - aimbs_put16(&fr->data, 0x001d); - aimbs_put16(&fr->data, 0x0008); - aimbs_put16(&fr->data, 0x0002); - aimbs_put16(&fr->data, 0x0404); - aimbs_put16(&fr->data, 0x0000); - aimbs_put16(&fr->data, 0x0000); + byte_stream_put16(&frame->data, 0x001d); + byte_stream_put16(&frame->data, 0x0008); + byte_stream_put16(&frame->data, 0x0002); + byte_stream_put16(&frame->data, 0x0404); + byte_stream_put16(&frame->data, 0x0000); + byte_stream_put16(&frame->data, 0x0000); } - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -921,14 +936,14 @@ * If the client does not send any data back, or the data does not match * the data that the specific client should have, the client will get the * following message from "AOL Instant Messenger": - * "You have been disconnected from the AOL Instant Message Service (SM) + * "You have been disconnected from the AOL Instant Message Service (SM) * for accessing the AOL network using unauthorized software. You can - * download a FREE, fully featured, and authorized client, here + * download a FREE, fully featured, and authorized client, here * http://www.aol.com/aim/download2.html" * The connection is then closed, receiving disconnect code 1, URL - * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html. + * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html. * - * Note, however, that numerous inconsistencies can cause the above error, + * Note, however, that numerous inconsistencies can cause the above error, * not just sending back a bad hash. Do not immediatly suspect this code * if you get disconnected. AOL and the open/free software community have * played this game for a couple years now, generating the above message @@ -938,7 +953,8 @@ * */ /* Subtype 0x001f - Client verification */ -static int memrequest(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +memrequest(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -946,16 +962,16 @@ aim_tlvlist_t *list; char *modname; - offset = aimbs_get32(bs); - len = aimbs_get32(bs); + offset = byte_stream_get32(bs); + len = byte_stream_get32(bs); list = aim_tlvlist_read(bs); modname = aim_tlv_getstr(list, 0x0001, 1); gaim_debug_info("oscar", "Got memory request for data at 0x%08lx (%d bytes) of requested %s\n", offset, len, modname ? modname : "aim.exe"); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, offset, len, modname); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, offset, len, modname); free(modname); aim_tlvlist_free(&list); @@ -964,25 +980,25 @@ } /* Subtype 0x0020 - Client verification reply */ -faim_export int aim_sendmemblock(OscarSession *sess, OscarConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag) +int +aim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !conn) + if (!od || !conn) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+16))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+2+16); - snacid = aim_cachesnac(sess, 0x0001, 0x0020, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, 0x0001, 0x0020, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0001, 0x0020, 0x0000, snacid); - aimbs_put16(&fr->data, 0x0010); /* md5 is always 16 bytes */ + aim_putsnac(&frame->data, 0x0001, 0x0020, 0x0000, snacid); + byte_stream_put16(&frame->data, 0x0010); /* md5 is always 16 bytes */ if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */ - aimbs_putraw(&fr->data, buf, 0x10); + byte_stream_putraw(&frame->data, buf, 0x10); } else if (buf && (len > 0)) { /* use input buffer */ GaimCipher *cipher; @@ -996,7 +1012,7 @@ gaim_cipher_context_digest(context, 16, digest, NULL); gaim_cipher_context_destroy(context); - aimbs_putraw(&fr->data, digest, 0x10); + byte_stream_putraw(&frame->data, digest, 0x10); } else if (len == 0) { /* no length, just hash NULL (buf is optional) */ GaimCipher *cipher; @@ -1015,7 +1031,7 @@ gaim_cipher_context_digest(context, 16, digest, NULL); gaim_cipher_context_destroy(context); - aimbs_putraw(&fr->data, digest, 0x10); + byte_stream_putraw(&frame->data, digest, 0x10); } else { @@ -1029,30 +1045,30 @@ if ((offset == 0x03ffffff) && (len == 0x03ffffff)) { #if 1 /* with "AnrbnrAqhfzcd" */ - aimbs_put32(&fr->data, 0x44a95d26); - aimbs_put32(&fr->data, 0xd2490423); - aimbs_put32(&fr->data, 0x93b8821f); - aimbs_put32(&fr->data, 0x51c54b01); + byte_stream_put32(&frame->data, 0x44a95d26); + byte_stream_put32(&frame->data, 0xd2490423); + byte_stream_put32(&frame->data, 0x93b8821f); + byte_stream_put32(&frame->data, 0x51c54b01); #else /* no filename */ - aimbs_put32(&fr->data, 0x1df8cbae); - aimbs_put32(&fr->data, 0x5523b839); - aimbs_put32(&fr->data, 0xa0e10db3); - aimbs_put32(&fr->data, 0xa46d3b39); + byte_stream_put32(&frame->data, 0x1df8cbae); + byte_stream_put32(&frame->data, 0x5523b839); + byte_stream_put32(&frame->data, 0xa0e10db3); + byte_stream_put32(&frame->data, 0xa46d3b39); #endif } else if ((offset == 0x00001000) && (len == 0x00000000)) { - aimbs_put32(&fr->data, 0xd41d8cd9); - aimbs_put32(&fr->data, 0x8f00b204); - aimbs_put32(&fr->data, 0xe9800998); - aimbs_put32(&fr->data, 0xecf8427e); + byte_stream_put32(&frame->data, 0xd41d8cd9); + byte_stream_put32(&frame->data, 0x8f00b204); + byte_stream_put32(&frame->data, 0xe9800998); + byte_stream_put32(&frame->data, 0xecf8427e); } else gaim_debug_warning("oscar", "sendmemblock: unknown hash request\n"); } - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -1064,30 +1080,31 @@ * status messages? It's also used to tell the client whether or not it * needs to upload an SSI buddy icon... who engineers this stuff, anyway? */ -static int aim_parse_extstatus(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +aim_parse_extstatus(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; guint16 type; guint8 flags, length; - type = aimbs_get16(bs); - flags = aimbs_get8(bs); - length = aimbs_get8(bs); + type = byte_stream_get16(bs); + flags = byte_stream_get8(bs); + length = byte_stream_get8(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) { switch (type) { case 0x0000: case 0x0001: { /* buddy icon checksum */ /* not sure what the difference between 1 and 0 is */ - guint8 *md5 = aimbs_getraw(bs, length); - ret = userfunc(sess, rx, type, flags, length, md5); + guint8 *md5 = byte_stream_getraw(bs, length); + ret = userfunc(od, conn, frame, type, flags, length, md5); free(md5); } break; case 0x0002: { /* available message */ /* there is a second length that is just for the message */ - char *msg = aimbs_getstr(bs, aimbs_get16(bs)); - ret = userfunc(sess, rx, msg); + char *msg = byte_stream_getstr(bs, byte_stream_get16(bs)); + ret = userfunc(od, conn, frame, msg); free(msg); } break; } @@ -1096,42 +1113,41 @@ return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0003) - return hostonline(sess, mod, rx, snac, bs); + return hostonline(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0005) - return redirect(sess, mod, rx, snac, bs); + return redirect(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0007) - return rateresp(sess, mod, rx, snac, bs); + return rateresp(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000a) - return ratechange(sess, mod, rx, snac, bs); + return ratechange(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000b) - return serverpause(sess, mod, rx, snac, bs); + return serverpause(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000d) - return serverresume(sess, mod, rx, snac, bs); + return serverresume(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000f) - return selfinfo(sess, mod, rx, snac, bs); + return selfinfo(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0010) - return evilnotify(sess, mod, rx, snac, bs); + return evilnotify(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0012) - return migrate(sess, mod, rx, snac, bs); + return migrate(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0013) - return motd(sess, mod, rx, snac, bs); + return motd(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0018) - return hostversions(sess, mod, rx, snac, bs); + return hostversions(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x001f) - return memrequest(sess, mod, rx, snac, bs); + return memrequest(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0021) - return aim_parse_extstatus(sess, mod, rx, snac, bs); + return aim_parse_extstatus(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int service_modfirst(OscarSession *sess, aim_module_t *mod) +int service_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0001; mod->version = 0x0003; mod->toolid = 0x0110;
--- a/src/protocols/oscar/family_popup.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_popup.c Fri Apr 07 05:10:56 2006 +0000 @@ -33,7 +33,8 @@ * The message is probably HTML. * */ -static int parsepopup(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +parsepopup(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { aim_rxcallback_t userfunc; aim_tlvlist_t *tl; @@ -49,8 +50,8 @@ height = aim_tlv_get16(tl, 0x0004, 1); delay = aim_tlv_get16(tl, 0x0005, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, msg, url, width, height, delay); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, msg, url, width, height, delay); aim_tlvlist_free(&tl); free(msg); @@ -59,18 +60,18 @@ return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0002) - return parsepopup(sess, mod, rx, snac, bs); + return parsepopup(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int popups_modfirst(OscarSession *sess, aim_module_t *mod) +int +popups_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x0008; mod->version = 0x0001; mod->toolid = 0x0104;
--- a/src/protocols/oscar/family_stats.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_stats.c Fri Apr 07 05:10:56 2006 +0000 @@ -25,32 +25,33 @@ #include <oscar.h> -static int reportinterval(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +reportinterval(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; guint16 interval; - interval = aimbs_get16(bs); + interval = byte_stream_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, interval); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, interval); return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0002) - return reportinterval(sess, mod, rx, snac, bs); + return reportinterval(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int stats_modfirst(OscarSession *sess, aim_module_t *mod) +int +stats_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x000b; mod->version = 0x0001; mod->toolid = 0x0104;
--- a/src/protocols/oscar/family_translate.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_translate.c Fri Apr 07 05:10:56 2006 +0000 @@ -31,7 +31,7 @@ #include "oscar.h" -faim_internal int translate_modfirst(OscarSession *sess, aim_module_t *mod) +int translate_modfirst(OscarData *od, aim_module_t *mod) { mod->family = 0x000c;
--- a/src/protocols/oscar/family_userlookup.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/family_userlookup.c Fri Apr 07 05:10:56 2006 +0000 @@ -32,20 +32,20 @@ * * XXX can this be integrated with the rest of the error handling? */ -static int error(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; aim_snac_t *snac2; /* XXX the modules interface should have already retrieved this for us */ - if (!(snac2 = aim_remsnac(sess, snac->id))) { + if (!(snac2 = aim_remsnac(od, snac->id))) { gaim_debug_misc("oscar", "search error: couldn't get a snac for 0x%08lx\n", snac->id); return 0; } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, snac2->data /* address */); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, snac2->data /* address */); /* XXX freesnac()? */ if (snac2) @@ -59,23 +59,25 @@ * Subtype 0x0002 * */ -faim_export int aim_search_address(OscarSession *sess, OscarConnection *conn, const char *address) +int aim_search_address(OscarData *od, const char *address) { - FlapFrame *fr; + FlapConnection *conn; + FlapFrame *frame; aim_snacid_t snacid; - if (!sess || !conn || !address) + conn = flap_connection_findbygroup(od, SNAC_FAMILY_USERLOOKUP); + + if (!od || !conn || !address) return -EINVAL; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+strlen(address)))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+strlen(address)); - snacid = aim_cachesnac(sess, 0x000a, 0x0002, 0x0000, strdup(address), strlen(address)+1); - aim_putsnac(&fr->data, 0x000a, 0x0002, 0x0000, snacid); - - aimbs_putstr(&fr->data, address); + snacid = aim_cachesnac(od, 0x000a, 0x0002, 0x0000, strdup(address), strlen(address)+1); + aim_putsnac(&frame->data, 0x000a, 0x0002, 0x0000, snacid); - aim_tx_enqueue(sess, fr); + byte_stream_putstr(&frame->data, address); + + flap_connection_send(conn, frame); return 0; } @@ -84,7 +86,7 @@ * Subtype 0x0003 * */ -static int reply(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int reply(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int j = 0, m, ret = 0; aim_tlvlist_t *tlvlist; @@ -93,29 +95,30 @@ aim_snac_t *snac2; char *searchaddr = NULL; - if ((snac2 = aim_remsnac(sess, snac->id))) + if ((snac2 = aim_remsnac(od, snac->id))) searchaddr = (char *)snac2->data; tlvlist = aim_tlvlist_read(bs); m = aim_tlvlist_count(&tlvlist); /* XXX uhm. - * This is the only place that uses something other than 1 for the 3rd + * This is the only place that uses something other than 1 for the 3rd * parameter to aim_tlv_gettlv_whatever(). */ - while ((cur = aim_tlv_getstr(tlvlist, 0x0001, j+1)) && j < m) { + while ((cur = aim_tlv_getstr(tlvlist, 0x0001, j+1)) && j < m) + { buf = realloc(buf, (j+1) * (MAXSNLEN+1)); strncpy(&buf[j * (MAXSNLEN+1)], cur, MAXSNLEN); free(cur); - j++; + j++; } aim_tlvlist_free(&tlvlist); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, searchaddr, j, buf); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, searchaddr, j, buf); /* XXX freesnac()? */ if (snac2) @@ -127,20 +130,20 @@ return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0001) - return error(sess, mod, rx, snac, bs); + return error(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0003) - return reply(sess, mod, rx, snac, bs); + return reply(od, conn, mod, frame, snac, bs); return 0; } -faim_internal int search_modfirst(OscarSession *sess, aim_module_t *mod) +int +search_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0x000a; mod->version = 0x0001; mod->toolid = 0x0110;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/oscar/flap_connection.c Fri Apr 07 05:10:56 2006 +0000 @@ -0,0 +1,815 @@ +/* + * 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 +*/ + +#include "oscar.h" + +#include "eventloop.h" + +#ifndef _WIN32 +#include <netdb.h> +#include <sys/socket.h> +#include <netinet/in.h> +#endif + +#ifdef _WIN32 +#include "win32dep.h" +#endif + +/** + * This sends a channel 1 SNAC containing the FLAP version. + * The FLAP version is sent by itself at the beginning of every + * connection to a FLAP server. It is always the very first + * packet sent by both the server and the client after the SYN, + * SYN/ACK, ACK handshake. + */ +void +flap_connection_send_version(OscarData *od, FlapConnection *conn) +{ + FlapFrame *frame; + + frame = flap_frame_new(od, 0x01, 4); + byte_stream_put32(&frame->data, 0x00000001); + flap_connection_send(conn, frame); +} + +/** + * This sends a channel 1 SNAC containing the FLAP version and + * the authentication cookie. This is sent when connecting to + * any FLAP server after the initial connection to the auth + * server. It is always the very first packet sent by both the + * server and the client after the SYN, SYN/ACK, ACK handshake. + */ +void +flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy) +{ + FlapFrame *frame; + aim_tlvlist_t *tl = NULL; + + frame = flap_frame_new(od, 0x01, 4 + 2 + 2 + length); + byte_stream_put32(&frame->data, 0x00000001); + aim_tlvlist_add_raw(&tl, 0x0006, length, chipsahoy); + aim_tlvlist_write(&frame->data, &tl); + aim_tlvlist_free(&tl); + + flap_connection_send(conn, frame); +} + +/** + * This sends an empty channel 4 SNAC. This is sent to signify + * that we're logging off. This shouldn't really be necessary-- + * usually the AIM server will detect that the TCP connection has + * been destroyed--but it's good practice. + */ +static void +flap_connection_send_close(OscarData *od, FlapConnection *conn) +{ + FlapFrame *frame; + + frame = flap_frame_new(od, 0x04, 0); + flap_connection_send(conn, frame); +} + +/** + * This sends an empty channel 5 SNAC. This is used as a keepalive + * packet in FLAP connections. WinAIM 4.x and higher send these + * _every minute_ to keep the connection alive. + */ +void +flap_connection_send_keepalive(OscarData *od, FlapConnection *conn) +{ + FlapFrame *frame; + + frame = flap_frame_new(od, 0x05, 0); + flap_connection_send(conn, frame); + + /* clean out SNACs over 60sec old */ + aim_cleansnacs(od, 60); +} + +/** + * Allocate a new empty connection structure. + * + * @param od The oscar session associated with this connection. + * @param type Type of connection to create + * + * @return Returns the new connection structure. + */ +FlapConnection * +flap_connection_new(OscarData *od, int type) +{ + FlapConnection *conn; + + conn = g_new0(FlapConnection, 1); + conn->od = od; + conn->buffer_outgoing = gaim_circ_buffer_new(0); + conn->inside = g_new0(aim_conn_inside_t, 1); + conn->fd = -1; + conn->subtype = -1; + conn->type = type; + + od->oscar_connections = g_list_prepend(od->oscar_connections, conn); + + return conn; +} + +/** + * Clone a FlapConnection. + * + * A new connection is allocated, and the values are filled in + * appropriately. + * + * @param od The session containing this connection. + * @param src The connection to clone. + * @return Returns a pointer to the new FlapConnection, or %NULL on error. + */ +FlapConnection * +flap_connection_clone(OscarData *od, FlapConnection *src) +{ + FlapConnection *conn; + + conn = flap_connection_new(od, src->type); + conn->fd = src->fd; + conn->type = src->type; + conn->subtype = src->subtype; + conn->seqnum = src->seqnum; + conn->internal = src->internal; + conn->lastactivity = src->lastactivity; + + if (src->inside != NULL) + { + /* + * XXX should clone this section as well, but since currently + * this function only gets called for some of that rendezvous + * crap, and not on SNAC connections, its probably okay for + * now. + * + */ + } + + return conn; +} + +/** + * Close (but not free) a connection. + * + * This leaves everything untouched except for setting the fd + * to -1 (used to recognize dead connections). + * + * @param conn The connection to close. + */ +void +flap_connection_close(OscarData *od, FlapConnection *conn) +{ + if (conn->fd == -1) + return; + + if (conn->type == SNAC_FAMILY_LOCATE) + flap_connection_send_close(od, conn); + + close(conn->fd); +} + +static void +flap_connection_destroy_snacgroups(struct snacgroup *head) +{ + struct snacgroup *sg; + for (sg = head; sg; ) + { + struct snacgroup *tmp; + + tmp = sg->next; + free(sg); + sg = tmp; + } +} + +static void +flap_connection_destroy_rates(struct rateclass *head) +{ + struct rateclass *rc; + + for (rc = head; rc; ) + { + struct rateclass *tmp; + struct snacpair *sp; + + tmp = rc->next; + + for (sp = rc->members; sp; ) { + struct snacpair *tmpsp; + + tmpsp = sp->next; + free(sp); + sp = tmpsp; + } + free(rc); + + rc = tmp; + } +} + +static gboolean +flap_connection_destroy_cb(gpointer data) +{ + FlapConnection *conn; + + conn = data; + + gaim_debug_info("oscar", "Destroying oscar connection of " + "type 0x%04hx\n", conn->type); + + flap_connection_close(conn->od, conn); + + if (conn->watcher_incoming != 0) + gaim_input_remove(conn->watcher_incoming); + if (conn->watcher_outgoing != 0) + gaim_input_remove(conn->watcher_outgoing); + g_free(conn->buffer_incoming.data.data); + gaim_circ_buffer_destroy(conn->buffer_outgoing); + + /* + * Free conn->internal, if necessary + */ + if (conn->type == SNAC_FAMILY_CHAT) + flap_connection_destroy_chat(conn->od, conn); + + if (conn->inside != NULL) + { + aim_conn_inside_t *inside = (aim_conn_inside_t *)conn->inside; + + flap_connection_destroy_snacgroups(inside->groups); + flap_connection_destroy_rates(inside->rates); + + free(inside); + } + + conn->od->oscar_connections = g_list_remove(conn->od->oscar_connections, conn); + + g_free(conn); + + return FALSE; +} + +void +flap_connection_destroy(FlapConnection *conn) +{ + if (conn->destroy_timeout != 0) + gaim_timeout_remove(conn->destroy_timeout); + flap_connection_destroy_cb(conn); +} + +/** + * Schedule Gaim to destroy the given FlapConnection as soon as we + * return control back to the program's main loop. We must do this + * if we want to destroy the connection but we are still using it + * for some reason. + */ +void +flap_connection_schedule_destroy(FlapConnection *conn) +{ + if (conn->destroy_timeout != 0) + /* Already taken care of */ + return; + + gaim_debug_info("oscar", "Scheduling destruction of FLAP " + "connection of type 0x%04hx\n", conn->type); + conn->destroy_timeout = gaim_timeout_add(0, flap_connection_destroy_cb, conn); +} + +/** + * In OSCAR, every connection has a set of SNAC groups associated + * with it. These are the groups that you can send over this connection + * without being guaranteed a "Not supported" SNAC error. + * + * The grand theory of things says that these associations transcend + * what libfaim calls "connection types" (conn->type). You can probably + * see the elegance here, but since I want to revel in it for a bit, you + * get to hear it all spelled out. + * + * So let us say that you have your core BOS connection running. One + * of your modules has just given you a SNAC of the group 0x0004 to send + * you. Maybe an IM destined for some twit in Greenland. So you start + * at the top of your connection list, looking for a connection that + * claims to support group 0x0004. You find one. Why, that neat BOS + * connection of yours can do that. So you send it on its way. + * + * Now, say, that fellow from Greenland has friends and they all want to + * meet up with you in a lame chat room. This has landed you a SNAC + * in the family 0x000e and you have to admit you're a bit lost. You've + * searched your connection list for someone who wants to make your life + * easy and deliver this SNAC for you, but there isn't one there. + * + * Here comes the good bit. Without even letting anyone know, particularly + * the module that decided to send this SNAC, and definitely not that twit + * in Greenland, you send out a service request. In this request, you have + * marked the need for a connection supporting group 0x000e. A few seconds + * later, you receive a service redirect with an IP address and a cookie in + * it. Great, you say. Now I have something to do. Off you go, making + * that connection. One of the first things you get from this new server + * is a message saying that indeed it does support the group you were looking + * for. So you continue and send rate confirmation and all that. + * + * Then you remember you had that SNAC to send, and now you have a means to + * do it, and you do, and everyone is happy. Except the Greenlander, who is + * still stuck in the bitter cold. + * + * Oh, and this is useful for building the Migration SNACs, too. In the + * future, this may help convince me to implement rate limit mitigation + * for real. We'll see. + * + * Just to make me look better, I'll say that I've known about this great + * scheme for quite some time now. But I still haven't convinced myself + * to make libfaim work that way. It would take a fair amount of effort, + * and probably some client API changes as well. (Whenever I don't want + * to do something, I just say it would change the client API. Then I + * instantly have a couple of supporters of not doing it.) + * + * Generally, addgroup is only called by the internal handling of the + * server ready SNAC. So if you want to do something before that, you'll + * have to be more creative. That is done rather early, though, so I don't + * think you have to worry about it. Unless you're me. I care deeply + * about such inane things. + * + */ +void +flap_connection_addgroup(FlapConnection *conn, guint16 group) +{ + aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; + struct snacgroup *sg; + + sg = g_new0(struct snacgroup, 1); + + gaim_debug_misc("oscar", "Adding group 0x%04x to connection " + "of type 0x%04hx\n", group, conn->type); + sg->group = group; + + sg->next = ins->groups; + ins->groups = sg; +} + +/** + * Find a FlapConnection that supports the given oscar + * family. + * + * TODO: This should be implemented to use a hash table. + */ +FlapConnection * +flap_connection_findbygroup(OscarData *od, guint16 group) +{ + GList *cur; + + for (cur = od->oscar_connections; cur != NULL; cur = cur->next) + { + FlapConnection *conn; + aim_conn_inside_t *ins; + struct snacgroup *sg; + + conn = cur->data; + ins = (aim_conn_inside_t *)conn->inside; + + for (sg = ins->groups; sg != NULL; sg = sg->next) + { + if (sg->group == group) + return conn; + } + } + + return NULL; +} + +/** + * Locates a connection of the specified type in the + * specified session. + * + * TODO: Use flap_connection_findbygroup everywhere and get rid of this. + * + * @param od The session to search. + * @param type The type of connection to look for. + * + * @return Returns the first connection found of the given target type, + * or NULL if none could be found. + */ +FlapConnection * +flap_connection_getbytype(OscarData *od, int type) +{ + GList *cur; + + for (cur = od->oscar_connections; cur != NULL; cur = cur->next) + { + FlapConnection *conn; + conn = cur->data; + if ((conn->type == type) && (conn->connected)) + return conn; + } + + return NULL; +} + +FlapConnection * +flap_connection_getbytype_all(OscarData *od, int type) +{ + GList *cur; + + for (cur = od->oscar_connections; cur; cur = cur->next) + { + FlapConnection *conn; + conn = cur->data; + if (conn->type == type) + return conn; + } + + return NULL; +} + +/** + * Allocate a new FLAP frame. + * + * @param channel The FLAP channel. This is almost always 2. + */ +FlapFrame * +flap_frame_new(OscarData *od, guint16 channel, int datalen) +{ + FlapFrame *frame; + + frame = g_new0(FlapFrame, 1); + frame->channel = channel; + + if (datalen > 0) + { + guint8 *data; + data = g_malloc(datalen); + byte_stream_init(&frame->data, data, datalen); + } + + return frame; +} + +/** + * Free a FlapFrame + * + * @param frame The frame to free. + * @return -1 on error; 0 on success. + */ +static void +flap_frame_destroy(FlapFrame *frame) +{ + free(frame->data.data); + free(frame); + + return; +} + +static void +parse_snac(OscarData *od, FlapConnection *conn, FlapFrame *frame) +{ + aim_module_t *cur; + aim_modsnac_t snac; + + if (byte_stream_empty(&frame->data) < 10) + return; + + snac.family = byte_stream_get16(&frame->data); + snac.subtype = byte_stream_get16(&frame->data); + snac.flags = byte_stream_get16(&frame->data); + snac.id = byte_stream_get32(&frame->data); + + /* SNAC flags are apparently uniform across all SNACs, so we handle them here */ + if (snac.flags & 0x0001) { + /* + * This means the SNAC will be followed by another SNAC with + * related information. We don't need to do anything about + * this here. + */ + } + if (snac.flags & 0x8000) { + /* + * This packet contains the version of the family that this SNAC is + * in. You get this when your SSI module is version 2 or higher. + * For now we have no need for this, but you could always save + * it as a part of aim_modnsac_t, or something. The format is... + * 2 byte length of total mini-header (which is 6 bytes), then TLV + * of type 0x0001, length 0x0002, value is the 2 byte version + * number + */ + byte_stream_advance(&frame->data, byte_stream_get16(&frame->data)); + } + + for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) { + + if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && + (cur->family != snac.family)) + continue; + + if (cur->snachandler(od, conn, cur, frame, &snac, &frame->data)) + return; + } +} + +static void +parse_fakesnac(OscarData *od, FlapConnection *conn, FlapFrame *frame, guint16 family, guint16 subtype) +{ + aim_module_t *cur; + aim_modsnac_t snac; + + snac.family = family; + snac.subtype = subtype; + snac.flags = snac.id = 0; + + for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) { + + if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && + (cur->family != snac.family)) + continue; + + if (cur->snachandler(od, conn, cur, frame, &snac, &frame->data)) + return; + } +} + +static void +parse_flap_ch4(OscarData *od, FlapConnection *conn, FlapFrame *frame) +{ + aim_tlvlist_t *tlvlist; + char *msg = NULL; + guint16 code = 0; + aim_rxcallback_t userfunc; + + if (byte_stream_empty(&frame->data) == 0) { + /* XXX should do something with this */ + return; + } + + /* Used only by the older login protocol */ + /* XXX remove this special case? */ + if (conn->type == SNAC_FAMILY_AUTH) + { + parse_fakesnac(od, conn, frame, 0x0017, 0x0003); + return; + } + + tlvlist = aim_tlvlist_read(&frame->data); + + if (aim_tlv_gettlv(tlvlist, 0x0009, 1)) + code = aim_tlv_get16(tlvlist, 0x0009, 1); + + if (aim_tlv_gettlv(tlvlist, 0x000b, 1)) + msg = aim_tlv_getstr(tlvlist, 0x000b, 1); + + if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR))) + userfunc(od, conn, frame, code, msg); + + aim_tlvlist_free(&tlvlist); + + free(msg); +} + +/** + * Takes a new incoming FLAP frame and sends it to the appropriate + * handler function to be parsed. + */ +static void +parse_flap(OscarData *od, FlapConnection *conn, FlapFrame *frame) +{ + if (frame->channel == 0x01) { + guint32 flap_version = byte_stream_get32(&frame->data); + if (flap_version != 0x00000001) + { + /* Error! */ + gaim_debug_warning("oscar", "Expecting FLAP version " + "0x00000001 but received FLAP version %08lx. Closing connection.\n", + flap_version); + flap_connection_schedule_destroy(conn); + } + else + conn->connected = TRUE; + + } else if (frame->channel == 0x02) { + parse_snac(od, conn, frame); + + } else if (frame->channel == 0x04) { + parse_flap_ch4(od, conn, frame); + + } else if (frame->channel == 0x05) { + /* TODO: Reset our keepalive watchdog? */ + + } +} + +/** + * Read in all available data on the socket for a given connection. + * All complete FLAPs handled immedate after they're received. + * Incomplete FLAP data is stored locally and appended to the next + * time this callback is triggered. + */ +void +flap_connection_recv_cb(gpointer data, gint source, GaimInputCondition cond) +{ + FlapConnection *conn; + ssize_t read; + guint8 header[6]; + + conn = data; + + /* Read data until we run out of data and break out of the loop */ + while (TRUE) + { + /* Start reading a new FLAP */ + if (conn->buffer_incoming.data.data == NULL) + { + /* Peek at the first 6 bytes to get the length */ + read = recv(conn->fd, &header, 6, MSG_PEEK); + + /* Check if the FLAP server closed the connection */ + if (read == 0) + { + /* TODO: Print an error? Server closed connection. */ + flap_connection_schedule_destroy(conn); + break; + } + + /* If there was an error then close the connection */ + if (read == -1) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No worries */ + break; + + /* Error! */ + /* TODO: Print an error? Lost connection with server. */ + flap_connection_schedule_destroy(conn); + break; + } + + /* If we don't even have a complete FLAP header then do nothing */ + if (read < 6) + break; + + /* Read the first 6 bytes (the FLAP header) */ + read = recv(conn->fd, &header, 6, 0); + + /* All FLAP frames must start with the byte 0x2a */ + if (aimutil_get8(&header[0]) != 0x2a) + { + flap_connection_schedule_destroy(conn); + break; + } + + /* Initialize a new temporary FlapFrame for incoming data */ + conn->buffer_incoming.channel = aimutil_get8(&header[1]); + conn->buffer_incoming.seqnum = aimutil_get16(&header[2]); + conn->buffer_incoming.data.len = aimutil_get16(&header[4]); + conn->buffer_incoming.data.data = g_new(guint8, conn->buffer_incoming.data.len); + conn->buffer_incoming.data.offset = 0; + } + + if (conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset) + { + /* Read data into the temporary FlapFrame until it is complete */ + read = recv(conn->fd, + &conn->buffer_incoming.data.data[conn->buffer_incoming.data.offset], + conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset, + 0); + + /* Check if the FLAP server closed the connection */ + if (read == 0) + { + flap_connection_schedule_destroy(conn); + break; + } + + if (read == -1) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No worries */ + break; + + /* Error! */ + /* TODO: Print an error? Lost connection with server. */ + flap_connection_schedule_destroy(conn); + break; + } + + conn->buffer_incoming.data.offset += read; + if (conn->buffer_incoming.data.offset < conn->buffer_incoming.data.len) + /* Waiting for more data to arrive */ + break; + } + + /* We have a complete FLAP! Handle it and continue reading */ + byte_stream_rewind(&conn->buffer_incoming.data); + parse_flap(conn->od, conn, &conn->buffer_incoming); + conn->lastactivity = time(NULL); + + g_free(conn->buffer_incoming.data.data); + conn->buffer_incoming.data.data = NULL; + } +} + +static void +send_cb(gpointer data, gint source, GaimInputCondition cond) +{ + FlapConnection *conn; + int writelen, ret; + + conn = data; + writelen = gaim_circ_buffer_get_max_read(conn->buffer_outgoing); + + if (writelen == 0) + { + gaim_input_remove(conn->watcher_outgoing); + conn->watcher_outgoing = 0; + return; + } + + ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); + if (ret <= 0) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No worries */ + return; + + /* Error! */ + flap_connection_schedule_destroy(conn); + return; + } + + gaim_circ_buffer_mark_read(conn->buffer_outgoing, ret); +} + +static void +flap_connection_send_byte_stream(ByteStream *bs, FlapConnection *conn, size_t count) +{ + if (conn == NULL) + return; + + /* Make sure we don't send past the end of the bs */ + if (count > byte_stream_empty(bs)) + count = byte_stream_empty(bs); /* truncate to remaining space */ + + if (count == 0) + return; + + /* Add everything to our outgoing buffer */ + gaim_circ_buffer_append(conn->buffer_outgoing, bs->data, count); + + /* If we haven't already started writing stuff, then start the cycle */ + if (conn->watcher_outgoing == 0) + { + conn->watcher_outgoing = gaim_input_add(conn->fd, + GAIM_INPUT_WRITE, send_cb, conn); + send_cb(conn, conn->fd, 0); + } +} + +static void +sendframe_flap(FlapConnection *conn, FlapFrame *frame) +{ + ByteStream bs; + int payloadlen, bslen; + + payloadlen = byte_stream_curpos(&frame->data); + + byte_stream_init(&bs, malloc(6 + payloadlen), 6 + payloadlen); + + /* FLAP header */ + byte_stream_put8(&bs, 0x2a); + byte_stream_put8(&bs, frame->channel); + byte_stream_put16(&bs, frame->seqnum); + byte_stream_put16(&bs, payloadlen); + + /* Payload */ + byte_stream_rewind(&frame->data); + byte_stream_putbs(&bs, &frame->data, payloadlen); + + bslen = byte_stream_curpos(&bs); + byte_stream_rewind(&bs); + flap_connection_send_byte_stream(&bs, conn, bslen); + + free(bs.data); /* XXX byte_stream_free */ +} + +void +flap_connection_send(FlapConnection *conn, FlapFrame *frame) +{ + frame->seqnum = ++(conn->seqnum); + sendframe_flap(conn, frame); + flap_frame_destroy(frame); +} +
--- a/src/protocols/oscar/misc.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/misc.c Fri Apr 07 05:10:56 2006 +0000 @@ -39,75 +39,75 @@ * back to the single. I don't see any advantage to doing it either way. * */ -faim_internal int aim_genericreq_n(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 subtype) +int +aim_genericreq_n(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid = 0x00000000; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10); - aim_putsnac(&fr->data, family, subtype, 0x0000, snacid); + aim_putsnac(&frame->data, family, subtype, 0x0000, snacid); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -faim_internal int aim_genericreq_n_snacid(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 subtype) +int +aim_genericreq_n_snacid(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10); - snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0); - aim_putsnac(&fr->data, family, subtype, 0x0000, snacid); + snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0); + aim_putsnac(&frame->data, family, subtype, 0x0000, snacid); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -faim_internal int aim_genericreq_l(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 subtype, guint32 *longdata) +int +aim_genericreq_l(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype, guint32 *longdata) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; if (!longdata) - return aim_genericreq_n(sess, conn, family, subtype); + return aim_genericreq_n(od, conn, family, subtype); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+4); - snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0); - aim_putsnac(&fr->data, family, subtype, 0x0000, snacid); - aimbs_put32(&fr->data, *longdata); + aim_putsnac(&frame->data, family, subtype, 0x0000, snacid); + byte_stream_put32(&frame->data, *longdata); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } -faim_internal int aim_genericreq_s(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 subtype, guint16 *shortdata) +int +aim_genericreq_s(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype, guint16 *shortdata) { - FlapFrame *fr; + FlapFrame *frame; aim_snacid_t snacid; if (!shortdata) - return aim_genericreq_n(sess, conn, family, subtype); + return aim_genericreq_n(od, conn, family, subtype); - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2))) - return -ENOMEM; + frame = flap_frame_new(od, 0x02, 10+2); - snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0); + snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0); - aim_putsnac(&fr->data, family, subtype, 0x0000, snacid); - aimbs_put16(&fr->data, *shortdata); + aim_putsnac(&frame->data, family, subtype, 0x0000, snacid); + byte_stream_put16(&frame->data, *shortdata); - aim_tx_enqueue(sess, fr); + flap_connection_send(conn, frame); return 0; } @@ -116,20 +116,21 @@ * Should be generic enough to handle the errors for all groups. * */ -static int generror(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +generror(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; int error = 0; aim_rxcallback_t userfunc; aim_snac_t *snac2; - snac2 = aim_remsnac(sess, snac->id); + snac2 = aim_remsnac(od, snac->id); - if (aim_bstream_empty(bs)) - error = aimbs_get16(bs); + if (byte_stream_empty(bs)) + error = byte_stream_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, error, snac2 ? snac2->data : NULL); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + ret = userfunc(od, conn, frame, error, snac2 ? snac2->data : NULL); if (snac2) free(snac2->data); @@ -138,24 +139,24 @@ return ret; } -static int snachandler(OscarSession *sess, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) +static int +snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - if (snac->subtype == 0x0001) - return generror(sess, mod, rx, snac, bs); + return generror(od, conn, mod, frame, snac, bs); else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) { aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx); + if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) + return userfunc(od, conn, frame); } return 0; } -faim_internal int misc_modfirst(OscarSession *sess, aim_module_t *mod) +int +misc_modfirst(OscarData *od, aim_module_t *mod) { - mod->family = 0xffff; mod->version = 0x0000; mod->flags = AIM_MODFLAG_MULTIFAMILY;
--- a/src/protocols/oscar/msgcookie.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/msgcookie.c Fri Apr 07 05:10:56 2006 +0000 @@ -40,30 +40,30 @@ * ->addtime of the found structure; otherwise adds the given cookie * to the cache * - * @param sess session to add to + * @param od session to add to * @param cookie pointer to struct to append * @return returns -1 on error, 0 on append, 1 on update. the cookie you pass * in may be free'd, so don't count on its value after calling this! */ -faim_internal int aim_cachecookie(OscarSession *sess, IcbmCookie *cookie) +int aim_cachecookie(OscarData *od, IcbmCookie *cookie) { IcbmCookie *newcook; - if (!sess || !cookie) + if (!od || !cookie) return -EINVAL; - newcook = aim_checkcookie(sess, cookie->cookie, cookie->type); + newcook = aim_checkcookie(od, cookie->cookie, cookie->type); if (newcook == cookie) { newcook->addtime = time(NULL); return 1; } else if (newcook) - aim_cookie_free(sess, newcook); + aim_cookie_free(od, newcook); cookie->addtime = time(NULL); - cookie->next = sess->msgcookies; - sess->msgcookies = cookie; + cookie->next = od->msgcookies; + od->msgcookies = cookie; return 0; } @@ -73,19 +73,19 @@ * * takes a cookie string and a cookie type and finds the cookie struct associated with that duple, removing it from the cookie list ikn the process. * - * @param sess session to grab cookie from + * @param od session to grab cookie from * @param cookie cookie string to look for * @param type cookie type to look for * @return if found, returns the struct; if none found (or on error), returns NULL: */ -faim_internal IcbmCookie *aim_uncachecookie(OscarSession *sess, guint8 *cookie, int type) +IcbmCookie *aim_uncachecookie(OscarData *od, guint8 *cookie, int type) { IcbmCookie *cur, **prev; - if (!cookie || !sess->msgcookies) + if (!cookie || !od->msgcookies) return NULL; - for (prev = &sess->msgcookies; (cur = *prev); ) { + for (prev = &od->msgcookies; (cur = *prev); ) { if ((cur->type == type) && (memcmp(cur->cookie, cookie, 8) == 0)) { *prev = cur->next; @@ -106,15 +106,14 @@ * @return returns NULL on error, a pointer to the newly-allocated * cookie on success. */ -faim_internal IcbmCookie *aim_mkcookie(guint8 *c, int type, void *data) +IcbmCookie *aim_mkcookie(guint8 *c, int type, void *data) { IcbmCookie *cookie; if (!c) return NULL; - if (!(cookie = calloc(1, sizeof(IcbmCookie)))) - return NULL; + cookie = calloc(1, sizeof(IcbmCookie)); cookie->data = data; cookie->type = type; @@ -126,21 +125,21 @@ /** * aim_checkcookie - check to see if a cookietuple has been cached * - * @param sess session to check for the cookie in + * @param od session to check for the cookie in * @param cookie pointer to the cookie string array * @param type type of the cookie to look for * @return returns a pointer to the cookie struct (still in the list) * on success; returns NULL on error/not found */ -faim_internal IcbmCookie *aim_checkcookie(OscarSession *sess, const guint8 *cookie, int type) +IcbmCookie *aim_checkcookie(OscarData *od, const guint8 *cookie, int type) { IcbmCookie *cur; - for (cur = sess->msgcookies; cur; cur = cur->next) { + for (cur = od->msgcookies; cur; cur = cur->next) { if ((cur->type == type) && (memcmp(cur->cookie, cookie, 8) == 0)) - return cur; + return cur; } return NULL; @@ -150,23 +149,23 @@ * aim_cookie_free - free an IcbmCookie struct * * this function removes the cookie *cookie from the list of cookies - * in sess, and then frees all memory associated with it. including + * in od, and then frees all memory associated with it. including * its data! if you want to use the private data after calling this, * make sure you copy it first. * - * @param sess session to remove the cookie from + * @param od session to remove the cookie from * @param cookie the address of a pointer to the cookie struct to remove * @return returns -1 on error, 0 on success. * */ -faim_internal int aim_cookie_free(OscarSession *sess, IcbmCookie *cookie) +int aim_cookie_free(OscarData *od, IcbmCookie *cookie) { IcbmCookie *cur, **prev; - if (!sess || !cookie) + if (!od || !cookie) return -EINVAL; - for (prev = &sess->msgcookies; (cur = *prev); ) { + for (prev = &od->msgcookies; (cur = *prev); ) { if (cur == cookie) *prev = cur->next; else @@ -180,16 +179,16 @@ } /* XXX I hate switch */ -faim_internal int aim_msgcookie_gettype(int reqclass) +int aim_msgcookie_gettype(int type) { /* XXX: hokey-assed. needs fixed. */ - switch(reqclass) { - case AIM_CAPS_BUDDYICON: return AIM_COOKIETYPE_OFTICON; - case AIM_CAPS_TALK: return AIM_COOKIETYPE_OFTVOICE; - case AIM_CAPS_DIRECTIM: return AIM_COOKIETYPE_OFTIMAGE; - case AIM_CAPS_CHAT: return AIM_COOKIETYPE_CHAT; - case AIM_CAPS_GETFILE: return AIM_COOKIETYPE_OFTGET; - case AIM_CAPS_SENDFILE: return AIM_COOKIETYPE_OFTSEND; + switch(type) { + case OSCAR_CAPABILITY_BUDDYICON: return AIM_COOKIETYPE_OFTICON; + case OSCAR_CAPABILITY_TALK: return AIM_COOKIETYPE_OFTVOICE; + case OSCAR_CAPABILITY_DIRECTIM: return AIM_COOKIETYPE_OFTIMAGE; + case OSCAR_CAPABILITY_CHAT: return AIM_COOKIETYPE_CHAT; + case OSCAR_CAPABILITY_GETFILE: return AIM_COOKIETYPE_OFTGET; + case OSCAR_CAPABILITY_SENDFILE: return AIM_COOKIETYPE_OFTSEND; default: return AIM_COOKIETYPE_UNKNOWN; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/oscar/odc.c Fri Apr 07 05:10:56 2006 +0000 @@ -0,0 +1,552 @@ +/* + * 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 +*/ + +/* From the oscar PRPL */ +#include "oscar.h" +#include "peer.h" + +/* From Gaim */ +#include "conversation.h" +#include "imgstore.h" +#include "util.h" + +/** + * Free any ODC related data and print a message to the conversation + * window based on conn->disconnect_reason. + */ +void +peer_odc_close(PeerConnection *conn) +{ + const gchar *tmp; + + if (conn->disconnect_reason == PEER_DISCONNECT_REMOTE_CLOSED) + { + tmp = _("Remote user closed the connection."); + } + else if (conn->disconnect_reason == PEER_DISCONNECT_REMOTE_REFUSED) + { + tmp = _("Remote user declined your request."); + } + else if (conn->disconnect_reason == PEER_DISCONNECT_LOST_CONNECTION) + { + tmp = _("Lost connection with remote user for an unknown reason."); + } + else if (conn->disconnect_reason == PEER_DISCONNECT_INVALID_DATA) + { + tmp = _("Received invalid data on connection."); + } + else if (conn->disconnect_reason == PEER_DISCONNECT_COULD_NOT_CONNECT) + { + tmp = _("Could not establish connection with remote user."); + } + else + /* + * We shouldn't print a message for some disconnect_reasons. + * Like PEER_DISCONNECT_LOCAL_CLOSED. + */ + tmp = NULL; + + if (tmp != NULL) + { + GaimAccount *account; + GaimConversation *conv; + + account = gaim_connection_get_account(conn->od->gc); + conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, conn->sn); + gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); + } + + if (conn->frame != NULL) + { + OdcFrame *frame; + frame = conn->frame; + g_free(frame->payload.data); + g_free(frame); + } +} + +/** + * Write the given OdcFrame to a ByteStream and send it out + * on the established PeerConnection. + */ +static void +peer_odc_send(PeerConnection *conn, OdcFrame *frame) +{ + GaimAccount *account; + const char *username; + size_t length; + ByteStream bs; + + gaim_debug_info("oscar", "Outgoing ODC frame to %s with " + "type=0x%04x, flags=0x%04x, payload length=%u\n", + conn->sn, frame->type, frame->flags, frame->payload.len); + + account = gaim_connection_get_account(conn->od->gc); + username = gaim_account_get_username(account); + memcpy(frame->sn, username, strlen(username)); + memcpy(frame->cookie, conn->cookie, 8); + + length = 76; + byte_stream_init(&bs, malloc(length + frame->payload.len), + length + frame->payload.len); + byte_stream_putraw(&bs, conn->magic, 4); + byte_stream_put16(&bs, length); + byte_stream_put16(&bs, frame->type); + byte_stream_put16(&bs, frame->subtype); + byte_stream_put16(&bs, 0x0000); + byte_stream_putraw(&bs, frame->cookie, 8); + byte_stream_put16(&bs, 0x0000); + byte_stream_put16(&bs, 0x0000); + byte_stream_put16(&bs, 0x0000); + byte_stream_put16(&bs, 0x0000); + byte_stream_put32(&bs, frame->payload.len); + byte_stream_put16(&bs, 0x0000); + byte_stream_put16(&bs, frame->encoding); + byte_stream_put16(&bs, 0x0000); + byte_stream_put16(&bs, frame->flags); + byte_stream_put16(&bs, 0x0000); + byte_stream_put16(&bs, 0x0000); + byte_stream_putraw(&bs, frame->sn, 32); + byte_stream_putraw(&bs, frame->payload.data, frame->payload.len); + + peer_connection_send(conn, &bs); + + free(bs.data); +} + +/** + * Send a very basic ODC frame (which contains the cookie) so that the + * remote user can verify that we are the person they were expecting. + * If we made an outgoing connection to then remote user, then we send + * this immediately. If the remote user connected to us, then we wait + * for the other person to send this to us, then we send one to them. + */ +void +peer_odc_send_cookie(PeerConnection *conn) +{ + OdcFrame frame; + + memset(&frame, 0, sizeof(OdcFrame)); + frame.type = 0x0001; + frame.subtype = 0x0006; + frame.flags = 0x0060; /* Maybe this means "we're sending the cookie"? */ + + peer_odc_send(conn, &frame); +} + +/** + * Send client-to-client typing notification over an established direct connection. + */ +void +peer_odc_send_typing(PeerConnection *conn, GaimTypingState typing) +{ + OdcFrame frame; + + memset(&frame, 0, sizeof(OdcFrame)); + frame.type = 0x0001; + frame.subtype = 0x0006; + if (typing == GAIM_TYPING) + frame.flags = 0x0002 | 0x0008; + else if (typing == GAIM_TYPED) + frame.flags = 0x0002 | 0x0004; + else + frame.flags = 0x0002; + + peer_odc_send(conn, &frame); +} + +/** + * Send client-to-client IM over an established direct connection. + * To send a direct IM, call this just like you would aim_send_im. + * + * @param conn The already-connected ODC connection. + * @param msg Null-terminated string to send. + * @param len The length of the message to send, including binary data. + * @param encoding See the AIM_CHARSET_* defines in oscar.h + * @param autoreply TRUE if this is any auto-reply. + */ +void +peer_odc_send_im(PeerConnection *conn, const char *msg, int len, int encoding, gboolean autoreply) +{ + OdcFrame frame; + + g_return_if_fail(msg != NULL); + g_return_if_fail(len > 0); + + memset(&frame, 0, sizeof(OdcFrame)); + frame.type = 0x0001; + frame.subtype = 0x0006; + frame.payload.len = len; + frame.encoding = encoding; + frame.flags = autoreply; + byte_stream_init(&frame.payload, malloc(len), len); + byte_stream_putraw(&frame.payload, (guint8 *)msg, len); + + peer_odc_send(conn, &frame); + + g_free(frame.payload.data); +} + +/** + * This is called after a direct IM has been received in its entirety. This + * function is passed a long chunk of data which contains the IM with any + * data chunks (images) appended to it. + * + * This function rips out all the data chunks and creates an imgstore for + * each one. In order to do this, it first goes through the IM and takes + * out all the IMG tags. When doing so, it rewrites the original IMG tag + * with one compatible with the imgstore Gaim core code. For each one, we + * then read in chunks of data from the end of the message and actually + * create the img store using the given data. + * + * For somewhat easy reference, here's a sample message + * (without the whitespace and asterisks): + * + * <HTML><BODY BGCOLOR="#ffffff"> + * <FONT LANG="0"> + * This is a really stupid picture:<BR> + * <IMG SRC="Sample.jpg" ID="1" WIDTH="283" HEIGHT="212" DATASIZE="9894"><BR> + * Yeah it is<BR> + * Here is another one:<BR> + * <IMG SRC="Soap Bubbles.bmp" ID="2" WIDTH="256" HEIGHT="256" DATASIZE="65978"> + * </FONT> + * </BODY></HTML> + * <BINARY> + * <DATA ID="1" SIZE="9894">datadatadatadata</DATA> + * <DATA ID="2" SIZE="65978">datadatadatadata</DATA> + * </BINARY> + * + * TODO: I think this does bad things when receiving + * multiple images in one IM. + */ +static void +peer_odc_handle_payload(PeerConnection *conn, const char *msg, size_t len, int encoding, gboolean autoreply) +{ + OscarData *od; + GaimConnection *gc; + GaimAccount *account; + GaimMessageFlags imflags; + gchar *utf8; + GString *newmsg; + GSList *images; + const char *msgend, *binary; + + od = conn->od; + gc = od->gc; + account = gaim_connection_get_account(gc); + + imflags = 0; + newmsg = g_string_new(""); + images = NULL; + + msgend = msg + len; + + if (autoreply) + imflags |= GAIM_MESSAGE_AUTO_RESP; + + /* message has a binary trailer */ + if ((binary = gaim_strcasestr(msg, "<binary>"))) + { + GData *attribs; + const char *tmp, *start, *end, *last = NULL; + + tmp = msg; + + /* for each valid image tag... */ + while (gaim_markup_find_tag("img", tmp, &start, &end, &attribs)) + { + const char *id, *src, *datasize; + const char *data = NULL; + char *tag = NULL; + size_t size; + int imgid = 0; + + /* update the location of the last img tag */ + last = end; + + /* grab attributes */ + id = g_datalist_get_data(&attribs, "id"); + src = g_datalist_get_data(&attribs, "src"); + datasize = g_datalist_get_data(&attribs, "datasize"); + + /* if we have id & datasize, build the data tag */ + if (id && datasize) + tag = g_strdup_printf("<data id=\"%s\" size=\"%s\">", id, datasize); + + /* if we have a tag, find the start of the data */ + if (tag && (data = gaim_strcasestr(binary, tag))) + data += strlen(tag); + + g_free(tag); + + /* check the data is here and store it */ + if (data + (size = atoi(datasize)) <= msgend) + imgid = gaim_imgstore_add(data, size, src); + + /* if we have a stored image... */ + if (imgid) { + /* append the message up to the tag */ + utf8 = gaim_plugin_oscar_decode_im_part(account, conn->sn, + encoding, 0x0000, tmp, start - tmp); + if (utf8 != NULL) { + newmsg = g_string_append(newmsg, utf8); + g_free(utf8); + } + + /* write the new image tag */ + g_string_append_printf(newmsg, "<IMG ID=\"%d\">", imgid); + + /* and record the image number */ + images = g_slist_append(images, GINT_TO_POINTER(imgid)); + } else { + /* otherwise, copy up to the end of the tag */ + utf8 = gaim_plugin_oscar_decode_im_part(account, conn->sn, + encoding, 0x0000, tmp, (end + 1) - tmp); + if (utf8 != NULL) { + newmsg = g_string_append(newmsg, utf8); + g_free(utf8); + } + } + + /* clear the attribute list */ + g_datalist_clear(&attribs); + + /* continue from the end of the tag */ + tmp = end + 1; + } + + /* append any remaining message data (without the > :-)) */ + if (last++ && (last < binary)) + newmsg = g_string_append_len(newmsg, last, binary - last); + + /* set the flag if we caught any images */ + if (images) + imflags |= GAIM_MESSAGE_IMAGES; + } else { + utf8 = gaim_plugin_oscar_decode_im_part(account, conn->sn, + encoding, 0x0000, msg, len); + if (utf8 != NULL) { + g_string_append(newmsg, utf8); + g_free(utf8); + } + } + + serv_got_im(gc, conn->sn, newmsg->str, imflags, time(NULL)); + + /* free the message */ + g_string_free(newmsg, TRUE); + + /* unref any images we allocated */ + if (images) { + GSList *tmp; + int id; + + for (tmp = images; tmp != NULL; tmp = tmp->next) { + id = GPOINTER_TO_INT(tmp->data); + gaim_imgstore_unref(id); + } + + g_slist_free(images); + } +} + +/** + * This is a gaim_input_add() watcher callback function for reading + * direct IM payload data. "Payload data" is always an IM and + * maybe some embedded images or files or something. The actual + * ODC frame is read using peer_connection_recv_cb(). We temporarily + * switch to this watcher callback ONLY to read the payload, and we + * switch back once we're done. + */ +static void +peer_odc_recv_cb(gpointer data, gint source, GaimInputCondition cond) +{ + PeerConnection *conn; + OdcFrame *frame; + ByteStream *bs; + ssize_t read; + + conn = data; + frame = conn->frame; + bs = &frame->payload; + + /* Read data into the temporary buffer until it is complete */ + read = recv(conn->fd, + &bs->data[bs->offset], + bs->len - bs->offset, + 0); + + /* Check if the remote user closed the connection */ + if (read == 0) + { + peer_connection_destroy(conn, PEER_DISCONNECT_REMOTE_CLOSED); + return; + } + + if (read == -1) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No worries */ + return; + + peer_connection_destroy(conn, PEER_DISCONNECT_LOST_CONNECTION); + return; + } + + bs->offset += read; + if (bs->offset < bs->len) + /* Waiting for more data to arrive */ + return; + + /* We have a complete ODC/OFT frame! Handle it and continue reading */ + byte_stream_rewind(bs); + peer_odc_handle_payload(conn, (const char *)bs->data, + bs->len, frame->encoding, frame->flags & 0x0001); + g_free(bs->data); + bs->data = NULL; + g_free(frame); + conn->frame = NULL; + + gaim_input_remove(conn->watcher_incoming); + conn->watcher_incoming = gaim_input_add(conn->fd, + GAIM_INPUT_READ, peer_connection_recv_cb, conn); +} + +/** + * Handle an incoming OdcFrame. If there is a payload associated + * with this frame, then we remove the old watcher and add the + * ODC watcher to read in the payload. + */ +void +peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs) +{ + GaimConnection *gc; + OdcFrame *frame; + + gc = conn->od->gc; + + frame = g_new0(OdcFrame, 1); + frame->type = byte_stream_get16(bs); + frame->subtype = byte_stream_get16(bs); + byte_stream_advance(bs, 2); + byte_stream_getrawbuf(bs, frame->cookie, 8); + byte_stream_advance(bs, 8); + frame->payload.len = byte_stream_get32(bs); + frame->encoding = byte_stream_get16(bs); + byte_stream_advance(bs, 4); + frame->flags = byte_stream_get16(bs); + byte_stream_advance(bs, 4); + byte_stream_getrawbuf(bs, frame->sn, 32); + + gaim_debug_info("oscar", "Incoming ODC frame from %s with " + "type=0x%04x, flags=0x%04x, payload length=%u\n", + frame->sn, frame->type, frame->flags, frame->payload.len); + + if (!conn->ready) + { + /* + * We need to verify the cookie so that we know we are + * connected to our friend and not a malicious middle man. + */ + + GaimAccount *account; + GaimConversation *conv; + + if (conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING) + { + if (memcmp(conn->cookie, frame->cookie, 8)) + { + /* + * Oh no! The user that connected to us did not send + * the correct cookie! They are not our friend. Go try + * to accept another connection? + */ + gaim_debug_info("oscar", "Received an incorrect cookie. " + "Closing connection.\n"); + peer_connection_destroy(conn, PEER_DISCONNECT_INVALID_DATA); + g_free(frame); + return; + } + + /* + * Ok, we know they are legit. Now be courteous and + * send them our cookie. Note: This doesn't seem + * to be necessary, but it also doesn't seem to hurt. + */ + peer_odc_send_cookie(conn); + } + + conn->ready = TRUE; + + /* + * If they connected to us then close the listener socket + * and send them our cookie. + */ + if (conn->listenerfd != -1) + { + close(conn->listenerfd); + conn->listenerfd = -1; + } + + /* Tell the local user that we are connected */ + account = gaim_connection_get_account(gc); + conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, conn->sn); + gaim_conversation_write(conv, NULL, _("Direct IM established"), + GAIM_MESSAGE_SYSTEM, time(NULL)); + } + + if ((frame->type != 0x0001) && (frame->subtype != 0x0006)) + { + gaim_debug_info("oscar", "Unknown ODC frame type 0x%04hx, " + "subtype 0x%04hx.\n", frame->type, frame->subtype); + return; + } + + if (frame->flags & 0x0008) + { + /* I had to leave this. It's just too funny. It reminds me of my sister. */ + gaim_debug_info("oscar", "ohmigod! %s has started typing " + "(DirectIM). He's going to send you a message! " + "*squeal*\n", conn->sn); + serv_got_typing(gc, conn->sn, 0, GAIM_TYPING); + } + else if (frame->flags & 0x0004) + { + serv_got_typing(gc, conn->sn, 0, GAIM_TYPED); + } + else + { + serv_got_typing_stopped(gc, conn->sn); + } + + if (frame->payload.len > 0) + { + /* We have payload data! Switch to the ODC watcher to read it. */ + frame->payload.data = g_new(guint8, frame->payload.len); + frame->payload.offset = 0; + conn->frame = frame; + gaim_input_remove(conn->watcher_incoming); + conn->watcher_incoming = gaim_input_add(conn->fd, + GAIM_INPUT_READ, peer_odc_recv_cb, conn); + return; + } + + g_free(frame); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/oscar/oft.c Fri Apr 07 05:10:56 2006 +0000 @@ -0,0 +1,602 @@ +/* + * 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 +*/ + +/* + * I feel like this is a good place to explain OFT, so I'm going to + * do just that. Each OFT packet has a header type. I guess this + * is pretty similar to the subtype of a SNAC packet. The type + * basically tells the other client the meaning of the OFT packet. + * There are two distinct types of file transfer, which I usually + * call "sendfile" and "getfile." Sendfile is when you send a file + * to another AIM user. Getfile is when you share a group of files, + * and other users request that you send them the files. + * + * A typical sendfile file transfer goes like this: + * 1) Sender sends a channel 2 ICBM telling the other user that + * we want to send them a file. At the same time, we open a + * listener socket (this should be done before sending the + * ICBM) on some port, and wait for them to connect to us. + * The ICBM we sent should contain our IP address and the port + * number that we're listening on. + * 2) The receiver connects to the sender on the given IP address + * and port. After the connection is established, the receiver + * sends an ICBM signifying that we are ready and waiting. + * 3) The sender sends an OFT PROMPT message over the OFT + * connection. + * 4) The receiver of the file sends back an exact copy of this + * OFT packet, except the cookie is filled in with the cookie + * from the ICBM. I think this might be an attempt to verify + * that the user that is connected is actually the guy that + * we sent the ICBM to. Oh, I've been calling this the ACK. + * 5) The sender starts sending raw data across the connection + * until the entire file has been sent. + * 6) The receiver knows the file is finished because the sender + * sent the file size in an earlier OFT packet. So then the + * receiver sends the DONE thingy (after filling in the + * "received" checksum and size) and closes the connection. + */ + +#include "oscar.h" +#include "peer.h" + +/** + * Calculate oft checksum of buffer + * + * Prevcheck should be 0xFFFF0000 when starting a checksum of a file. The + * checksum is kind of a rolling checksum thing, so each time you get bytes + * of a file you just call this puppy and it updates the checksum. You can + * calculate the checksum of an entire file by calling this in a while or a + * for loop, or something. + * + * Thanks to Graham Booker for providing this improved checksum routine, + * which is simpler and should be more accurate than Josh Myer's original + * code. -- wtm + * + * This algorithm works every time I have tried it. The other fails + * sometimes. So, AOL who thought this up? It has got to be the weirdest + * checksum I have ever seen. + * + * @param buffer Buffer of data to checksum. Man I'd like to buff her... + * @param bufsize Size of buffer. + * @param prevchecksum Previous checksum. + */ +static guint32 +peer_oft_checksum_chunk(const guint8 *buffer, int bufferlen, guint32 prevchecksum) +{ + guint32 checksum, oldchecksum; + int i; + unsigned short val; + + checksum = (prevchecksum >> 16) & 0xffff; + for (i = 0; i < bufferlen; i++) + { + oldchecksum = checksum; + if (i & 1) + val = buffer[i]; + else + val = buffer[i] << 8; + checksum -= val; + /* + * The following appears to be necessary.... It happens + * every once in a while and the checksum doesn't fail. + */ + if (checksum > oldchecksum) + checksum--; + } + checksum = ((checksum & 0x0000ffff) + (checksum >> 16)); + checksum = ((checksum & 0x0000ffff) + (checksum >> 16)); + return checksum << 16; +} + +static guint32 +peer_oft_checksum_file(char *filename) +{ + FILE *fd; + guint32 checksum = 0xffff0000; + + if ((fd = fopen(filename, "rb"))) + { + int bytes; + guint8 buffer[1024]; + + while ((bytes = fread(buffer, 1, 1024, fd)) != 0) + checksum = peer_oft_checksum_chunk(buffer, bytes, checksum); + fclose(fd); + } + + return checksum; +} + +/** + * Free any OFT related data. + */ +void +peer_oft_close(PeerConnection *conn) +{ + /* + * If canceled by local user, and we're receiving a file, and + * we're not connected/ready then send an ICBM cancel message. + */ + if ((gaim_xfer_get_status(conn->xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) && + !conn->ready) + { + aim_im_sendch2_cancel(conn); + } + + if (conn->sending_data_timer != 0) + { + gaim_timeout_remove(conn->sending_data_timer); + conn->sending_data_timer = 0; + } +} + +/** + * Write the given OftFrame to a ByteStream and send it out + * on the established PeerConnection. + */ +static void +peer_oft_send(PeerConnection *conn, OftFrame *frame) +{ + size_t length; + ByteStream bs; + + length = 192 + MAX(64, frame->name_length + 1); + byte_stream_init(&bs, malloc(length), length); + byte_stream_putraw(&bs, conn->magic, 4); + byte_stream_put16(&bs, length); + byte_stream_put16(&bs, frame->type); + byte_stream_putraw(&bs, frame->cookie, 8); + byte_stream_put16(&bs, frame->encrypt); + byte_stream_put16(&bs, frame->compress); + byte_stream_put16(&bs, frame->totfiles); + byte_stream_put16(&bs, frame->filesleft); + byte_stream_put16(&bs, frame->totparts); + byte_stream_put16(&bs, frame->partsleft); + byte_stream_put32(&bs, frame->totsize); + byte_stream_put32(&bs, frame->size); + byte_stream_put32(&bs, frame->modtime); + byte_stream_put32(&bs, frame->checksum); + byte_stream_put32(&bs, frame->rfrcsum); + byte_stream_put32(&bs, frame->rfsize); + byte_stream_put32(&bs, frame->cretime); + byte_stream_put32(&bs, frame->rfcsum); + byte_stream_put32(&bs, frame->nrecvd); + byte_stream_put32(&bs, frame->recvcsum); + byte_stream_putraw(&bs, frame->idstring, 32); + byte_stream_put8(&bs, frame->flags); + byte_stream_put8(&bs, frame->lnameoffset); + byte_stream_put8(&bs, frame->lsizeoffset); + byte_stream_putraw(&bs, frame->dummy, 69); + byte_stream_putraw(&bs, frame->macfileinfo, 16); + byte_stream_put16(&bs, frame->nencode); + byte_stream_put16(&bs, frame->nlanguage); + /* + * The name can be more than 64 characters, but if it is less than + * 64 characters it is padded with NULLs. + */ + byte_stream_putraw(&bs, frame->name, MAX(64, frame->name_length + 1)); + + peer_connection_send(conn, &bs); + + free(bs.data); +} + +void +peer_oft_send_prompt(PeerConnection *conn) +{ + conn->xferdata.type = PEER_TYPE_PROMPT; + peer_oft_send(conn, &conn->xferdata); +} + +static void +peer_oft_send_ack(PeerConnection *conn) +{ + conn->xferdata.type = PEER_TYPE_ACK; + + /* Fill in the cookie */ + memcpy(conn->xferdata.cookie, conn->cookie, 8); + + peer_oft_send(conn, &conn->xferdata); +} + +static void +peer_oft_send_done(PeerConnection *conn) +{ + conn->xferdata.type = PEER_TYPE_DONE; + conn->xferdata.filesleft = 0; + conn->xferdata.partsleft = 0; + conn->xferdata.nrecvd = gaim_xfer_get_bytes_sent(conn->xfer); + peer_oft_send(conn, &conn->xferdata); +} + +/** + * This function exists so that we don't remove the outgoing + * data watcher while we're still sending data. In most cases + * any data we're sending will be instantly wisked away to a TCP + * buffer maintained by our operating system... but we want to + * make sure the core doesn't start sending file data while + * we're still sending OFT frame data. That would be bad. + */ +static gboolean +start_transfer_when_done_sending_data(gpointer data) +{ + PeerConnection *conn; + + conn = data; + + if (gaim_circ_buffer_get_max_read(conn->buffer_outgoing) == 0) + { + conn->sending_data_timer = 0; + gaim_input_remove(conn->watcher_incoming); + conn->watcher_incoming = 0; + conn->xfer->fd = conn->fd; + conn->fd = -1; + gaim_xfer_start(conn->xfer, conn->xfer->fd, NULL, 0); + return FALSE; + } + + return TRUE; +} + +/** + * This function is similar to the above function, except instead + * of starting the xfer it will destroy the connection. This is + * used when you want to send one final message across the peer + * connection, and then close everything. + */ +static gboolean +destroy_connection_when_done_sending_data(gpointer data) +{ + PeerConnection *conn; + + conn = data; + + if (gaim_circ_buffer_get_max_read(conn->buffer_outgoing) == 0) + { + conn->sending_data_timer = 0; + peer_connection_destroy(conn, conn->disconnect_reason); + return FALSE; + } + + return TRUE; +} + +/* + * This is called when a buddy sends us some file info. This happens when they + * are sending a file to you, and you have just established a connection to them. + * You should send them the exact same info except use the real cookie. We also + * get like totally ready to like, receive the file, kay? + */ +static void +peer_oft_recv_frame_prompt(PeerConnection *conn, OftFrame *frame) +{ + /* Record the file information and send an ack */ + memcpy(&conn->xferdata, frame, sizeof(OftFrame)); + peer_oft_send_ack(conn); + + /* Remove our watchers and use the file transfer watchers in the core */ + gaim_input_remove(conn->watcher_incoming); + conn->watcher_incoming = 0; + conn->sending_data_timer = gaim_timeout_add(100, + start_transfer_when_done_sending_data, conn); +} + +/** + * We are sending a file to someone else. They have just acknowledged our + * prompt, so we want to start sending data like there's no tomorrow. + */ +static void +peer_oft_recv_frame_ack(PeerConnection *conn, OftFrame *frame) +{ + if (memcmp(conn->cookie, frame->cookie, 8)) + { + gaim_debug_info("oscar", "Received an incorrect cookie. " + "Closing connection.\n"); + peer_connection_destroy(conn, PEER_DISCONNECT_INVALID_DATA); + return; + } + + /* Remove our watchers and use the file transfer watchers in the core */ + gaim_input_remove(conn->watcher_incoming); + conn->watcher_incoming = 0; + conn->sending_data_timer = gaim_timeout_add(100, + start_transfer_when_done_sending_data, conn); +} + +/* + * We just sent a file to someone. They said they got it and everything, + * so we can close our direct connection and what not. + */ +static void +peer_oft_recv_frame_done(PeerConnection *conn, OftFrame *frame) +{ + if (frame->nrecvd == frame->size) + gaim_xfer_set_completed(conn->xfer, TRUE); + + gaim_input_remove(conn->watcher_incoming); + conn->watcher_incoming = 0; + conn->xfer->fd = conn->fd; + conn->fd = -1; + gaim_xfer_end(conn->xfer); +} + +/** + * Handle an incoming OftFrame. If there is a payload associated + * with this frame, then we remove the old watcher and add the + * OFT watcher to read in the payload. + */ +void +peer_oft_recv_frame(PeerConnection *conn, ByteStream *bs) +{ + OftFrame frame; + + frame.type = byte_stream_get16(bs); + byte_stream_getrawbuf(bs, frame.cookie, 8); + frame.encrypt = byte_stream_get16(bs); + frame.compress = byte_stream_get16(bs); + frame.totfiles = byte_stream_get16(bs); + frame.filesleft = byte_stream_get16(bs); + frame.totparts = byte_stream_get16(bs); + frame.partsleft = byte_stream_get16(bs); + frame.totsize = byte_stream_get32(bs); + frame.size = byte_stream_get32(bs); + frame.modtime = byte_stream_get32(bs); + frame.checksum = byte_stream_get32(bs); + frame.rfrcsum = byte_stream_get32(bs); + frame.rfsize = byte_stream_get32(bs); + frame.cretime = byte_stream_get32(bs); + frame.rfcsum = byte_stream_get32(bs); + frame.nrecvd = byte_stream_get32(bs); + frame.recvcsum = byte_stream_get32(bs); + byte_stream_getrawbuf(bs, frame.idstring, 32); + frame.flags = byte_stream_get8(bs); + frame.lnameoffset = byte_stream_get8(bs); + frame.lsizeoffset = byte_stream_get8(bs); + byte_stream_getrawbuf(bs, frame.dummy, 69); + byte_stream_getrawbuf(bs, frame.macfileinfo, 16); + frame.nencode = byte_stream_get16(bs); + frame.nlanguage = byte_stream_get16(bs); + frame.name_length = bs->len - 186; + frame.name = byte_stream_getraw(bs, frame.name_length); + + gaim_debug_info("oscar", "Incoming OFT frame from %s with " + "type=0x%04x\n", conn->sn, frame.type); + + /* TODOFT: peer_oft_dirconvert_fromstupid(frame->name); */ + + if (frame.type == PEER_TYPE_PROMPT) + peer_oft_recv_frame_prompt(conn, &frame); + else if (frame.type == PEER_TYPE_ACK) + peer_oft_recv_frame_ack(conn, &frame); + else if (frame.type == PEER_TYPE_DONE) + peer_oft_recv_frame_done(conn, &frame); + + free(frame.name); +} + +/*******************************************************************/ +/* Begin GaimXfer callbacks for use when receiving a file */ +/*******************************************************************/ + +void +peer_oft_recvcb_init(GaimXfer *xfer) +{ + PeerConnection *conn; + + conn = xfer->data; + conn->flags |= PEER_CONNECTION_FLAG_APPROVED; + peer_connection_trynext(conn); +} + +void +peer_oft_recvcb_end(GaimXfer *xfer) +{ + PeerConnection *conn; + + conn = xfer->data; + + /* Tell the other person that we've received everything */ + conn->fd = conn->xfer->fd; + conn->xfer->fd = -1; + peer_oft_send_done(conn); + + conn->disconnect_reason = PEER_DISCONNECT_DONE; + conn->sending_data_timer = gaim_timeout_add(100, + destroy_connection_when_done_sending_data, conn); +} + +void +peer_oft_recvcb_ack_recv(GaimXfer *xfer, const guchar *buffer, size_t size) +{ + PeerConnection *conn; + + /* Update our rolling checksum. Like Walmart, yo. */ + conn = xfer->data; + conn->xferdata.recvcsum = peer_oft_checksum_chunk(buffer, + size, conn->xferdata.recvcsum); +} + +/*******************************************************************/ +/* End GaimXfer callbacks for use when receiving a file */ +/*******************************************************************/ + +/*******************************************************************/ +/* Begin GaimXfer callbacks for use when sending a file */ +/*******************************************************************/ + +void +peer_oft_sendcb_init(GaimXfer *xfer) +{ + PeerConnection *conn; + + conn = xfer->data; + conn->flags |= PEER_CONNECTION_FLAG_APPROVED; + + /* Keep track of file transfer info */ + conn->xferdata.totfiles = 1; + conn->xferdata.filesleft = 1; + conn->xferdata.totparts = 1; + conn->xferdata.partsleft = 1; + conn->xferdata.totsize = gaim_xfer_get_size(xfer); + conn->xferdata.size = gaim_xfer_get_size(xfer); + conn->xferdata.checksum = 0xffff0000; + conn->xferdata.rfrcsum = 0xffff0000; + conn->xferdata.rfcsum = 0xffff0000; + conn->xferdata.recvcsum = 0xffff0000; + strncpy((gchar *)conn->xferdata.idstring, "OFT_Windows ICBMFT V1.1 32", 31); + conn->xferdata.modtime = 0; + conn->xferdata.cretime = 0; + xfer->filename = g_path_get_basename(xfer->local_filename); + conn->xferdata.name = (guchar *)g_strdup(xfer->filename); + conn->xferdata.name_length = strlen(xfer->filename); + + /* Calculating the checksum can take a very long time for large files */ + gaim_debug_info("oscar","calculating file checksum\n"); + conn->xferdata.checksum = peer_oft_checksum_file(xfer->local_filename); + gaim_debug_info("oscar","checksum calculated\n"); + + /* Start the connection process */ + peer_connection_trynext(conn); +} + +/* + * AIM file transfers aren't really meant to be thought + * of as a transferring just a single file. The rendezvous + * establishes a connection between two computers, and then + * those computers can use the same connection for transferring + * multiple files. So we don't want the Gaim core up and closing + * the socket all willy-nilly. We want to do that in the oscar + * prpl, whenever one side or the other says they're finished + * using the connection. There might be a better way to intercept + * the socket from the core... + */ +void +peer_oft_sendcb_ack(GaimXfer *xfer, const guchar *buffer, size_t size) +{ + PeerConnection *conn; + + conn = xfer->data; + + /* + * If we're done sending, intercept the socket from the core ft code + * and wait for the other guy to send the "done" OFT packet. + */ + if (gaim_xfer_get_bytes_remaining(xfer) <= 0) + { + gaim_input_remove(xfer->watcher); + conn->fd = xfer->fd; + xfer->fd = -1; + conn->watcher_incoming = gaim_input_add(conn->fd, + GAIM_INPUT_READ, peer_connection_recv_cb, conn); + } +} + +/*******************************************************************/ +/* End GaimXfer callbacks for use when sending a file */ +/*******************************************************************/ + +/*******************************************************************/ +/* Begin GaimXfer callbacks for use when sending and receiving */ +/*******************************************************************/ + +void +peer_oft_cb_generic_cancel(GaimXfer *xfer) +{ + PeerConnection *conn; + + conn = xfer->data; + + if (conn == NULL) + return; + + peer_connection_destroy(conn, PEER_DISCONNECT_LOCAL_CLOSED); +} + +/*******************************************************************/ +/* End GaimXfer callbacks for use when sending and receiving */ +/*******************************************************************/ + +#if 0 +/* + * This little area in oscar.c is the nexus of file transfer code, + * so I wrote a little explanation of what happens. I am such a + * ninja. + * + * The series of events for a file send is: + * -Create xfer and call gaim_xfer_request (this happens in oscar_ask_sendfile) + * -User chooses a file and oscar_xfer_init is called. It establishes a + * listening socket, then asks the remote user to connect to us (and + * gives them the file name, port, IP, etc.) + * -They connect to us and we send them an PEER_TYPE_PROMPT (this happens + * in peer_oft_recv_frame_established) + * -They send us an PEER_TYPE_ACK and then we start sending data + * -When we finish, they send us an PEER_TYPE_DONE and they close the + * connection. + * -We get drunk because file transfer kicks ass. + * + * The series of events for a file receive is: + * -Create xfer and call gaim_xfer request (this happens in incomingim_chan2) + * -Gaim user selects file to name and location to save file to and + * oscar_xfer_init is called + * -It connects to the remote user using the IP they gave us earlier + * -After connecting, they send us an PEER_TYPE_PROMPT. In reply, we send + * them an PEER_TYPE_ACK. + * -They begin to send us lots of raw data. + * -When they finish sending data we send an PEER_TYPE_DONE and then close + * the connection. + * + * Update August 2005: + * The series of events for transfers has been seriously complicated by the addition + * of transfer redirects and proxied connections. I could throw a whole lot of words + * at trying to explain things here, but it probably wouldn't do much good. To get + * a better idea of what happens, take a look at the diagrams and documentation + * from my Summer of Code project. -- Jonathan Clark + */ + +/** + * Convert the directory separator from / (0x2f) to ^A (0x01) + * + * @param name The filename to convert. + */ +static void +peer_oft_dirconvert_tostupid(char *name) +{ + while (name[0]) { + if (name[0] == 0x01) + name[0] = G_DIR_SEPARATOR; + name++; + } +} + +/** + * Convert the directory separator from ^A (0x01) to / (0x2f) + * + * @param name The filename to convert. + */ +static void +peer_oft_dirconvert_fromstupid(char *name) +{ + while (name[0]) { + if (name[0] == G_DIR_SEPARATOR) + name[0] = 0x01; + name++; + } +} +#endif
--- a/src/protocols/oscar/oscar.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/oscar.c Fri Apr 07 05:10:56 2006 +0000 @@ -34,7 +34,6 @@ #include "conversation.h" #include "core.h" #include "debug.h" -#include "ft.h" #include "imgstore.h" #include "network.h" #include "notify.h" @@ -48,15 +47,15 @@ #include "oscar.h" #include "peer.h" -#define OSCAR_STATUS_ID_INVISIBLE "invisible" -#define OSCAR_STATUS_ID_OFFLINE "offline" -#define OSCAR_STATUS_ID_AVAILABLE "available" -#define OSCAR_STATUS_ID_AWAY "away" -#define OSCAR_STATUS_ID_DND "dnd" -#define OSCAR_STATUS_ID_NA "na" -#define OSCAR_STATUS_ID_OCCUPIED "occupied" -#define OSCAR_STATUS_ID_FREE4CHAT "free4chat" -#define OSCAR_STATUS_ID_CUSTOM "custom" +#define OSCAR_STATUS_ID_INVISIBLE "invisible" +#define OSCAR_STATUS_ID_OFFLINE "offline" +#define OSCAR_STATUS_ID_AVAILABLE "available" +#define OSCAR_STATUS_ID_AWAY "away" +#define OSCAR_STATUS_ID_DND "dnd" +#define OSCAR_STATUS_ID_NA "na" +#define OSCAR_STATUS_ID_OCCUPIED "occupied" +#define OSCAR_STATUS_ID_FREE4CHAT "free4chat" +#define OSCAR_STATUS_ID_CUSTOM "custom" #define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3" @@ -67,69 +66,24 @@ #define OSCAR_DEFAULT_AUTHORIZATION TRUE #define OSCAR_DEFAULT_HIDE_IP TRUE #define OSCAR_DEFAULT_WEB_AWARE FALSE -#define OSCAR_DEFAULT_USE_RV_PROXY TRUE - -/* Milliseconds each file transfer ip address will be given to make a connection. */ -#define FT_CLIENTIP_TIMEOUT 1000 /* 5000 */ -#define FT_VERIFIEDIP_TIMEOUT 5000 /* 15000 */ -#define FT_REDIR_TIMEOUT 10000 /* 20000 */ /* Time to wait for redirected transfer */ -#define FT_PROXYIP_TIMEOUT 300000 /* 120000 */ /* Time to create a checksum for VERY large files */ - -static int caps_aim = AIM_CAPS_CHAT | AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_INTEROPERATE | AIM_CAPS_ICHAT; -static int caps_icq = AIM_CAPS_BUDDYICON | AIM_CAPS_DIRECTIM | AIM_CAPS_SENDFILE | AIM_CAPS_ICQUTF8 | AIM_CAPS_INTEROPERATE | AIM_CAPS_ICHAT; +#define OSCAR_DEFAULT_USE_RV_PROXY FALSE + +static int caps_aim = OSCAR_CAPABILITY_CHAT | OSCAR_CAPABILITY_BUDDYICON | OSCAR_CAPABILITY_DIRECTIM | OSCAR_CAPABILITY_SENDFILE | OSCAR_CAPABILITY_INTEROPERATE | OSCAR_CAPABILITY_ICHAT; +static int caps_icq = OSCAR_CAPABILITY_BUDDYICON | OSCAR_CAPABILITY_DIRECTIM | OSCAR_CAPABILITY_SENDFILE | OSCAR_CAPABILITY_ICQUTF8 | OSCAR_CAPABILITY_INTEROPERATE | OSCAR_CAPABILITY_ICHAT; static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02}; static guint8 features_icq[] = {0x01, 0x06}; static guint8 features_icq_offline[] = {0x01}; static guint8 ck[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -typedef struct _OscarData OscarData; -struct _OscarData { - OscarSession *sess; - OscarConnection *conn; - - guint cnpa; - guint paspa; - guint emlpa; - guint icopa; - - gboolean iconconnecting; - gboolean set_icon; - - GSList *create_rooms; - - gboolean conf; - gboolean reqemail; - gboolean setemail; - char *email; - gboolean setnick; - char *newsn; - gboolean chpass; - char *oldp; - char *newp; - - GSList *oscar_chats; - GSList *direct_ims; - GSList *file_transfers; - GHashTable *buddyinfo; - GSList *requesticon; - - gboolean killme; - gboolean icq; - guint icontimer; - guint getblisttimer; - guint getinfotimer; - gint timeoffset; - - struct { - guint maxwatchers; /* max users who can watch you */ - guint maxbuddies; /* max users you can watch */ - guint maxgroups; /* max groups in server list */ - guint maxpermits; /* max users on permit list */ - guint maxdenies; /* max users on deny list */ - guint maxsiglen; /* max size (bytes) of profile */ - guint maxawaymsglen; /* max size (bytes) of posted away message */ - } rights; +typedef struct _NewFlapConnectionData NewFlapConnectionData; +struct _NewFlapConnectionData +{ + GaimConnection *gc; + FlapConnection *conn; + guint16 cookielen; + guint8 *cookie; + gpointer data; }; struct create_room { @@ -137,13 +91,13 @@ int exchange; }; -struct chat_connection { +struct chat_connection +{ char *name; char *show; /* AOL did something funny to us */ guint16 exchange; guint16 instance; - OscarConnection *conn; - int inpa; + FlapConnection *conn; int id; GaimConnection *gc; /* i hate this. */ GaimConversation *conv; /* bah. */ @@ -151,23 +105,10 @@ int maxvis; }; -struct oscar_direct_im { - GaimConnection *gc; - char name[80]; - int watcher; - OscarConnection *conn; - gboolean connected; - gboolean gpc_pend; - gboolean killme; - gboolean donttryagain; -}; - -struct ask_direct { - GaimConnection *gc; - char *sn; - char ip[64]; - guint8 cookie[8]; - gboolean donttryagain; +struct oscar_ask_directim_data +{ + OscarData *od; + char *who; }; /* @@ -175,7 +116,7 @@ * Some other info is maintained by locate.c, and I'd like to move * the rest of this to libfaim, mostly im.c * - * TODO: I think all of this should use the status API. + * TODO: More of this should use the status API. */ struct buddyinfo { gboolean typingnot; @@ -229,86 +170,62 @@ static int msgerrreasonlen = 25; /* All the libfaim->gaim callback functions */ -static int gaim_parse_auth_resp (OscarSession *, FlapFrame *, ...); -static int gaim_parse_login (OscarSession *, FlapFrame *, ...); -static int gaim_parse_auth_securid_request(OscarSession *, FlapFrame *, ...); -static int gaim_handle_redirect (OscarSession *, FlapFrame *, ...); -static int gaim_info_change (OscarSession *, FlapFrame *, ...); -static int gaim_account_confirm (OscarSession *, FlapFrame *, ...); -static int gaim_parse_oncoming (OscarSession *, FlapFrame *, ...); -static int gaim_parse_offgoing (OscarSession *, FlapFrame *, ...); -static int gaim_parse_incoming_im(OscarSession *, FlapFrame *, ...); -static int gaim_parse_misses (OscarSession *, FlapFrame *, ...); -static int gaim_parse_clientauto (OscarSession *, FlapFrame *, ...); -static int gaim_parse_userinfo (OscarSession *, FlapFrame *, ...); -static int gaim_reqinfo_timeout (OscarSession *, FlapFrame *, ...); -static int gaim_got_infoblock (OscarSession *sess, FlapFrame *fr, ...); -static int gaim_parse_motd (OscarSession *, FlapFrame *, ...); -static int gaim_chatnav_info (OscarSession *, FlapFrame *, ...); -static int gaim_conv_chat_join (OscarSession *, FlapFrame *, ...); -static int gaim_conv_chat_leave (OscarSession *, FlapFrame *, ...); -static int gaim_conv_chat_info_update (OscarSession *, FlapFrame *, ...); -static int gaim_conv_chat_incoming_msg(OscarSession *, FlapFrame *, ...); -static int gaim_email_parseupdate(OscarSession *, FlapFrame *, ...); -static int gaim_icon_error (OscarSession *, FlapFrame *, ...); -static int gaim_icon_parseicon (OscarSession *, FlapFrame *, ...); -static int oscar_icon_req (OscarSession *, FlapFrame *, ...); -static int gaim_parse_msgack (OscarSession *, FlapFrame *, ...); -static int gaim_parse_ratechange (OscarSession *, FlapFrame *, ...); -static int gaim_parse_evilnotify (OscarSession *, FlapFrame *, ...); -static int gaim_parse_searcherror(OscarSession *, FlapFrame *, ...); -static int gaim_parse_searchreply(OscarSession *, FlapFrame *, ...); -static int gaim_bosrights (OscarSession *, FlapFrame *, ...); -static int gaim_connerr (OscarSession *, FlapFrame *, ...); -static int conninitdone_admin (OscarSession *, FlapFrame *, ...); -static int conninitdone_bos (OscarSession *, FlapFrame *, ...); -static int conninitdone_chatnav (OscarSession *, FlapFrame *, ...); -static int conninitdone_chat (OscarSession *, FlapFrame *, ...); -static int conninitdone_email (OscarSession *, FlapFrame *, ...); -static int conninitdone_icon (OscarSession *, FlapFrame *, ...); -static int gaim_parse_msgerr (OscarSession *, FlapFrame *, ...); -static int gaim_parse_mtn (OscarSession *, FlapFrame *, ...); -static int gaim_parse_locaterights(OscarSession *, FlapFrame *, ...); -static int gaim_parse_buddyrights(OscarSession *, FlapFrame *, ...); -static int gaim_parse_locerr (OscarSession *, FlapFrame *, ...); -static int gaim_icbm_param_info (OscarSession *, FlapFrame *, ...); -static int gaim_parse_genericerr (OscarSession *, FlapFrame *, ...); -static int gaim_memrequest (OscarSession *, FlapFrame *, ...); -static int gaim_selfinfo (OscarSession *, FlapFrame *, ...); -static int gaim_offlinemsg (OscarSession *, FlapFrame *, ...); -static int gaim_offlinemsgdone (OscarSession *, FlapFrame *, ...); -static int gaim_icqalias (OscarSession *, FlapFrame *, ...); -static int gaim_icqinfo (OscarSession *, FlapFrame *, ...); -static int gaim_popup (OscarSession *, FlapFrame *, ...); - -static int gaim_ssi_parseerr (OscarSession *, FlapFrame *, ...); -static int gaim_ssi_parserights (OscarSession *, FlapFrame *, ...); -static int gaim_ssi_parselist (OscarSession *, FlapFrame *, ...); -static int gaim_ssi_parseack (OscarSession *, FlapFrame *, ...); -static int gaim_ssi_parseadd (OscarSession *, FlapFrame *, ...); -static int gaim_ssi_authgiven (OscarSession *, FlapFrame *, ...); -static int gaim_ssi_authrequest (OscarSession *, FlapFrame *, ...); -static int gaim_ssi_authreply (OscarSession *, FlapFrame *, ...); -static int gaim_ssi_gotadded (OscarSession *, FlapFrame *, ...); - -/* for DirectIM/image transfer */ -static int gaim_odc_initiate (OscarSession *, FlapFrame *, ...); -static int gaim_odc_incoming (OscarSession *, FlapFrame *, ...); -static int gaim_odc_typing (OscarSession *, FlapFrame *, ...); -static int gaim_odc_update_ui (OscarSession *, FlapFrame *, ...); - -/* for file transfer */ -static int oscar_sendfile_estblsh(OscarSession *, FlapFrame *, ...); -static int oscar_sendfile_prompt (OscarSession *, FlapFrame *, ...); -static int oscar_sendfile_ack (OscarSession *, FlapFrame *, ...); -static int oscar_sendfile_done (OscarSession *, FlapFrame *, ...); +static int gaim_parse_auth_resp (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_login (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_auth_securid_request(OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_handle_redirect (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_info_change (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_account_confirm (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_oncoming (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_offgoing (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_incoming_im(OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_misses (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_clientauto (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_userinfo (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_got_infoblock (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_motd (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_chatnav_info (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_conv_chat_join (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_conv_chat_leave (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_conv_chat_info_update (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_conv_chat_incoming_msg(OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_email_parseupdate(OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_icon_error (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...); +static int oscar_icon_req (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_msgack (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_ratechange (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_evilnotify (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_bosrights (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_connerr (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_msgerr (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_mtn (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_locaterights(OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_buddyrights(OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_locerr (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_icbm_param_info (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_parse_genericerr (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_memrequest (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_selfinfo (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_offlinemsg (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_offlinemsgdone (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_icqalias (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_icqinfo (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_popup (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_ssi_parseerr (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_ssi_parserights (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_ssi_parselist (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_ssi_parseack (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_ssi_parseadd (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_ssi_authgiven (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_ssi_authrequest (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_ssi_authreply (OscarData *, FlapConnection *, FlapFrame *, ...); +static int gaim_ssi_gotadded (OscarData *, FlapConnection *, FlapFrame *, ...); static gboolean gaim_icon_timerfunc(gpointer data); -static void oscar_callback(gpointer data, gint source, GaimInputCondition condition); -static void oscar_xfer_init_recv(GaimXfer *xfer); -static void oscar_xfer_init_send(GaimXfer *xfer); - -static void oscar_direct_im_initiate(GaimConnection *gc, const char *who, const guchar *cookie); + static void recent_buddies_cb(const char *name, GaimPrefType type, gconstpointer value, gpointer data); static void oscar_set_info(GaimConnection *gc, const char *info); static void oscar_set_info_and_status(GaimAccount *account, gboolean setinfo, const char *rawinfo, gboolean setstatus, GaimStatus *status); @@ -321,20 +238,24 @@ g_free(data); } -static void oscar_free_buddyinfo(void *data) { - struct buddyinfo *bi = data; - g_free(bi); -} - -static guint32 oscar_charset_check(const char *utf8) +/** + * Determine how we can send this message. Per the warnings elsewhere + * in this file, these little checks determine the simplest encoding + * we can use for a given message send using it. + */ +static guint32 +oscar_charset_check(const char *utf8) { int i = 0; int charset = AIM_CHARSET_ASCII; - /* Determine how we can send this message. Per the warnings elsewhere - * in this file, these little checks determine the simplest encoding - * we can use for a given message send using it. */ - while (utf8[i]) { + /* + * Can we get away with using our custom encoding? + * TODO: This should actually try using the encoding specified in + * the account editor. + */ + while (utf8[i]) + { if ((unsigned char)utf8[i] > 0x7f) { /* not ASCII! */ charset = AIM_CHARSET_CUSTOM; @@ -342,7 +263,12 @@ } i++; } - while (utf8[i]) { + + /* + * Must we send this message as UNICODE (in the UCS-2BE encoding)? + */ + while (utf8[i]) + { /* ISO-8859-1 is 0x00-0xbf in the first byte * followed by 0xc0-0xc3 in the second */ if ((unsigned char)utf8[i] < 0x80) { @@ -360,12 +286,13 @@ return charset; } -/* +/** * Take a string of the form charset="bleh" where bleh is * one of us-ascii, utf-8, iso-8859-1, or unicode-2-0, and * return a newly allocated string containing bleh. */ -static gchar *oscar_encoding_extract(const char *encoding) +static gchar * +oscar_encoding_extract(const char *encoding) { gchar *ret = NULL; char *begin, *end; @@ -390,7 +317,7 @@ return ret; } -static gchar * +gchar * oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen) { gchar *utf8 = NULL; @@ -418,7 +345,7 @@ if (utf8 == NULL) { if (textlen != 0 && *text != '\0' && !g_utf8_validate(text, textlen, NULL)) - utf8 = g_strdup(_("(There was an error receiving this message. The buddy you are speaking to most likely has a buggy client.)")); + utf8 = g_strdup(_("(There was an error receiving this message. The buddy you are speaking with is probably using a different encoding than expected. If you know what encoding he is using, you can specify it in the advanced account options for your AIM/ICQ account.)")); else utf8 = g_strndup(text, textlen); } @@ -426,7 +353,8 @@ return utf8; } -static gchar *oscar_utf8_try_convert(GaimAccount *account, const gchar *msg) +static gchar * +oscar_utf8_try_convert(GaimAccount *account, const gchar *msg) { const char *charset = NULL; char *ret = NULL; @@ -472,7 +400,7 @@ return ret; } -/* +/** * This attemps to decode an incoming IM into a UTF8 string. * * We try decoding using two different character sets. The charset @@ -482,7 +410,7 @@ * able to deal with that crap, then people complain like banshees. * charsetstr1 is always set to what the correct encoding should be. */ -static gchar * +gchar * gaim_plugin_oscar_decode_im_part(GaimAccount *account, const char *sourcesn, guint16 charset, guint16 charsubset, const gchar *data, gsize datalen) { gchar *ret = NULL; @@ -525,7 +453,7 @@ return ret; } -/* +/** * Figure out what encoding to use when sending a given outgoing message. */ static void @@ -557,9 +485,9 @@ * as UCS-2BE. */ if ((destsn != NULL) && aim_sn_is_icq(destsn)) - userinfo = aim_locate_finduserinfo(od->sess, destsn); - - if ((userinfo != NULL) && (userinfo->capabilities & AIM_CAPS_ICQUTF8)) + userinfo = aim_locate_finduserinfo(od, destsn); + + if ((userinfo != NULL) && (userinfo->capabilities & OSCAR_CAPABILITY_ICQUTF8)) { GaimBuddy *b; b = gaim_find_buddy(account, destsn); @@ -692,78 +620,78 @@ if (!caps) { return NULL; - } else while (bit <= AIM_CAPS_LAST) { + } else while (bit <= OSCAR_CAPABILITY_LAST) { if (bit & caps) { switch (bit) { - case AIM_CAPS_BUDDYICON: + case OSCAR_CAPABILITY_BUDDYICON: tmp = _("Buddy Icon"); break; - case AIM_CAPS_TALK: + case OSCAR_CAPABILITY_TALK: tmp = _("Voice"); break; - case AIM_CAPS_DIRECTIM: + case OSCAR_CAPABILITY_DIRECTIM: tmp = _("AIM Direct IM"); break; - case AIM_CAPS_CHAT: + case OSCAR_CAPABILITY_CHAT: tmp = _("Chat"); break; - case AIM_CAPS_GETFILE: + case OSCAR_CAPABILITY_GETFILE: tmp = _("Get File"); break; - case AIM_CAPS_SENDFILE: + case OSCAR_CAPABILITY_SENDFILE: tmp = _("Send File"); break; - case AIM_CAPS_GAMES: - case AIM_CAPS_GAMES2: + case OSCAR_CAPABILITY_GAMES: + case OSCAR_CAPABILITY_GAMES2: tmp = _("Games"); break; - case AIM_CAPS_ADDINS: + case OSCAR_CAPABILITY_ADDINS: tmp = _("Add-Ins"); break; - case AIM_CAPS_SENDBUDDYLIST: + case OSCAR_CAPABILITY_SENDBUDDYLIST: tmp = _("Send Buddy List"); break; - case AIM_CAPS_ICQ_DIRECT: + case OSCAR_CAPABILITY_ICQ_DIRECT: tmp = _("ICQ Direct Connect"); break; - case AIM_CAPS_APINFO: + case OSCAR_CAPABILITY_APINFO: tmp = _("AP User"); break; - case AIM_CAPS_ICQRTF: + case OSCAR_CAPABILITY_ICQRTF: tmp = _("ICQ RTF"); break; - case AIM_CAPS_EMPTY: + case OSCAR_CAPABILITY_EMPTY: tmp = _("Nihilist"); break; - case AIM_CAPS_ICQSERVERRELAY: + case OSCAR_CAPABILITY_ICQSERVERRELAY: tmp = _("ICQ Server Relay"); break; - case AIM_CAPS_ICQUTF8OLD: + case OSCAR_CAPABILITY_ICQUTF8OLD: tmp = _("Old ICQ UTF8"); break; - case AIM_CAPS_TRILLIANCRYPT: + case OSCAR_CAPABILITY_TRILLIANCRYPT: tmp = _("Trillian Encryption"); break; - case AIM_CAPS_ICQUTF8: + case OSCAR_CAPABILITY_ICQUTF8: tmp = _("ICQ UTF8"); break; - case AIM_CAPS_HIPTOP: + case OSCAR_CAPABILITY_HIPTOP: tmp = _("Hiptop"); break; - case AIM_CAPS_SECUREIM: + case OSCAR_CAPABILITY_SECUREIM: tmp = _("Security Enabled"); break; - case AIM_CAPS_VIDEO: + case OSCAR_CAPABILITY_VIDEO: tmp = _("Video Chat"); break; /* Not actually sure about this one... WinAIM doesn't show anything */ - case AIM_CAPS_ICHATAV: + case OSCAR_CAPABILITY_ICHATAV: tmp = _("iChat AV"); break; - case AIM_CAPS_LIVEVIDEO: + case OSCAR_CAPABILITY_LIVEVIDEO: tmp = _("Live Video"); break; - case AIM_CAPS_CAMERA: + case OSCAR_CAPABILITY_CAMERA: tmp = _("Camera"); break; default: @@ -828,7 +756,7 @@ return; if (userinfo == NULL) - userinfo = aim_locate_finduserinfo(od->sess, b->name); + userinfo = aim_locate_finduserinfo(od, b->name); if (b == NULL) b = gaim_find_buddy(account, userinfo->sn); @@ -850,8 +778,8 @@ gaim_status_get_name(status)); } } else { - tmp = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name); - if (aim_ssi_waitingforauth(od->sess->ssi.local, tmp, b->name)) + tmp = aim_ssi_itemlist_findparentname(od->ssi.local, b->name); + if (aim_ssi_waitingforauth(od->ssi.local, tmp, b->name)) oscar_string_append(gc->account, str, newline, _("Status"), _("Not Authorized")); else @@ -878,7 +806,7 @@ } if ((b != NULL) && (b->name != NULL) && (g != NULL) && (g->name != NULL)) { - tmp = aim_ssi_getcomment(od->sess->ssi.local, g->name, b->name); + tmp = aim_ssi_getcomment(od->ssi.local, g->name, b->name); if (tmp != NULL) { char *tmp2 = g_markup_escape_text(tmp, strlen(tmp)); g_free(tmp); @@ -935,7 +863,7 @@ } static struct chat_connection * -find_oscar_chat_by_conn(GaimConnection *gc, OscarConnection *conn) +find_oscar_chat_by_conn(GaimConnection *gc, FlapConnection *conn) { OscarData *od = (OscarData *)gc->proto_data; GSList *cur; @@ -969,6 +897,14 @@ } static void +oscar_chat_destroy(struct chat_connection *cc) +{ + g_free(cc->name); + g_free(cc->show); + g_free(cc); +} + +static void oscar_chat_kill(GaimConnection *gc, struct chat_connection *cc) { OscarData *od = (OscarData *)gc->proto_data; @@ -978,913 +914,297 @@ /* Destroy the chat_connection */ od->oscar_chats = g_slist_remove(od->oscar_chats, cc); - if (cc->inpa > 0) - gaim_input_remove(cc->inpa); - oscar_connection_destroy(od->sess, cc->conn); - g_free(cc->name); - g_free(cc->show); - g_free(cc); -} - -/***************************************************************************** - * Begin scary direct im stuff - *****************************************************************************/ - -static struct oscar_direct_im *oscar_direct_im_find(OscarData *od, const char *who) { - GSList *d = od->direct_ims; - struct oscar_direct_im *m = NULL; - - while (d) { - m = (struct oscar_direct_im *)d->data; - if (!aim_sncmp(who, m->name)) - return m; - d = d->next; - } - - return NULL; -} - -static void oscar_direct_im_destroy(OscarData *od, struct oscar_direct_im *dim) -{ - gaim_debug_info("oscar", - "destroying Direct IM for %s.\n", dim->name); - - od->direct_ims = g_slist_remove(od->direct_ims, dim); - if (dim->gpc_pend) { - dim->killme = TRUE; - return; - } - if (dim->watcher) - gaim_input_remove(dim->watcher); - if (dim->conn) - oscar_connection_destroy(od->sess, dim->conn); - g_free(dim); -} - -/* the only difference between this and destroy is this writes a conv message */ -static void oscar_direct_im_disconnect(OscarData *od, struct oscar_direct_im *dim) -{ - GaimConversation *conv; - char buf[256]; - - gaim_debug_info("oscar", - "%s disconnected Direct IM.\n", dim->name); - - if (dim->connected) - g_snprintf(buf, sizeof buf, _("Direct IM with %s closed"), dim->name); - else - g_snprintf(buf, sizeof buf, _("Direct IM with %s failed"), dim->name); - - conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, dim->name, - gaim_connection_get_account(dim->gc)); - - if (conv) { - gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); - } else { - gaim_notify_error(dim->gc, NULL, _("Direct Connect failed"), buf); - } - - oscar_direct_im_destroy(od, dim); - - return; -} - -/* oops i made two of these. this one just calls the other one. */ -static void gaim_odc_disconnect(OscarSession *sess, OscarConnection *conn) -{ - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; - struct oscar_direct_im *dim; - char *sn; - - sn = g_strdup(aim_odc_getsn(conn)); - dim = oscar_direct_im_find(od, sn); - oscar_direct_im_disconnect(od, dim); - g_free(sn); -} - -static void destroy_direct_im_request(struct ask_direct *d) { - gaim_debug_info("oscar", "Freeing DirectIM prompts.\n"); - - g_free(d->sn); - g_free(d); -} - -/* this is just a gaim_proxy_connect cb that sets up the rest of the cbs */ -static void oscar_odc_callback(gpointer data, gint source, GaimInputCondition condition) { - struct oscar_direct_im *dim = data; - GaimConnection *gc = dim->gc; - OscarData *od = gc->proto_data; - GaimConversation *conv; - char buf[256]; - struct sockaddr name; - socklen_t name_len = 1; - - g_return_if_fail(gc != NULL); - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - - dim->gpc_pend = FALSE; - if (dim->killme) { - oscar_direct_im_destroy(od, dim); - return; - } - - if (!g_list_find(gaim_connections_get_all(), gc)) { - oscar_direct_im_destroy(od, dim); - return; - } - - if (source < 0) { - if (dim->donttryagain) { - oscar_direct_im_disconnect(od, dim); - return; - } else { - guchar cookie[8]; - char *who = g_strdup(dim->name); - const guchar *tmp = aim_odc_getcookie(dim->conn); - - memcpy(cookie, tmp, 8); - oscar_direct_im_destroy(od, dim); - oscar_direct_im_initiate(gc, who, cookie); - gaim_debug_info("oscar", "asking direct im initiator to connect to us\n"); - g_free(who); - return; - } - } - - dim->conn->fd = source; - aim_conn_completeconnect(od->sess, dim->conn); - conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, dim->gc->account, dim->name); - - /* This is the best way to see if we're connected or not */ - /* Is this really needed? */ - if (getpeername(source, &name, &name_len) == 0) { - g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name); - dim->connected = TRUE; - gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); - dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, oscar_callback, dim->conn); - } else { - if (dim->donttryagain) { - oscar_direct_im_disconnect(od, dim); - return; - } else { - guchar cookie[8]; - char *who = g_strdup(dim->name); - const guchar *tmp = aim_odc_getcookie(dim->conn); - - memcpy(cookie, tmp, 8); - oscar_direct_im_destroy(od, dim); - oscar_direct_im_initiate(gc, who, cookie); - gaim_debug_info("oscar", "asking direct im initiator to connect to us\n"); - g_free(who); - return; - } - } - - -} - -static void accept_direct_im_request(struct ask_direct *d) { - GaimConnection *gc = d->gc; - OscarData *od; - struct oscar_direct_im *dim; - char *host; int port = 5190; - int i, rc; - char *tmp; - GaimConversation *conv; - - if (!g_list_find(gaim_connections_get_all(), gc)) { - destroy_direct_im_request(d); - return; - } - - od = (OscarData *)gc->proto_data; - gaim_debug_info("oscar", "Accepted DirectIM.\n"); - - dim = oscar_direct_im_find(od, d->sn); - if (dim && dim->connected) { - destroy_direct_im_request(d); /* 40 */ /* what does that 40 mean? */ - gaim_debug_info("oscar", "Wait, we're already connected, ignoring DirectIM.\n"); - return; - } - dim = g_new0(struct oscar_direct_im, 1); - dim->gc = d->gc; - dim->donttryagain = d->donttryagain; - g_snprintf(dim->name, sizeof dim->name, "%s", d->sn); - - dim->conn = aim_odc_connect(od->sess, d->sn, NULL, d->cookie); - od->direct_ims = g_slist_append(od->direct_ims, dim); - if (!dim->conn) { - oscar_direct_im_disconnect(od, dim); - destroy_direct_im_request(d); - return; - } - - aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, - PEER_TYPE_DIRECTIMINCOMING, gaim_odc_incoming, 0); - aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, - PEER_TYPE_DIRECTIMTYPING, gaim_odc_typing, 0); - aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_SPECIAL, - AIM_CB_SPECIAL_IMAGETRANSFER, gaim_odc_update_ui, 0); - - gaim_debug_info("oscar", "ip is %s.\n", d->ip); - for (i = 0; i < (int)strlen(d->ip); i++) { - if (d->ip[i] == ':') { - port = atoi(&(d->ip[i+1])); - break; - } - } - host = g_strndup(d->ip, i); - dim->conn->status |= AIM_CONN_STATUS_INPROGRESS; - dim->gpc_pend = TRUE; - rc = gaim_proxy_connect(gc->account, host, port, oscar_odc_callback, dim); - - conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, dim->gc->account, d->sn); - tmp = g_strdup_printf(_("Attempting to connect to %s at %s:%hu for Direct IM."), - d->sn, host, port); - gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); - g_free(tmp); - - g_free(host); - if (rc < 0) { - dim->gpc_pend = FALSE; - oscar_direct_im_disconnect(od, dim); - destroy_direct_im_request(d); - return; - } - - destroy_direct_im_request(d); - - return; -} - -/* - * We have just established a socket with the other dude, so set up some handlers. - */ -static int gaim_odc_initiate(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; - GaimConversation *conv; - struct oscar_direct_im *dim; - char buf[256]; - char *sn; - va_list ap; - OscarConnection *newconn, *listenerconn; - - va_start(ap, fr); - newconn = va_arg(ap, OscarConnection *); - listenerconn = va_arg(ap, OscarConnection *); - va_end(ap); - - oscar_connection_destroy(sess, listenerconn); - - sn = g_strdup(aim_odc_getsn(newconn)); - - gaim_debug_info("oscar", "DirectIM: initiate success to %s\n", sn); - dim = oscar_direct_im_find(od, sn); - - conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, dim->gc->account, sn); - gaim_input_remove(dim->watcher); - dim->conn = newconn; - dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, oscar_callback, dim->conn); - dim->connected = TRUE; - g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), sn); - g_free(sn); - gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL)); - - aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMINCOMING, gaim_odc_incoming, 0); - aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMTYPING, gaim_odc_typing, 0); - aim_conn_addhandler(sess, newconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER, gaim_odc_update_ui, 0); - - return 1; -} - -/* - * This is called when each chunk of an image is received. It can be used to - * update a progress bar, or to eat lots of dry cat food. Wet cat food is - * nasty, you sicko. - */ -static int gaim_odc_update_ui(OscarSession *sess, FlapFrame *fr, ...) { - va_list ap; - char *sn; - double percent; - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; - struct oscar_direct_im *dim; - - va_start(ap, fr); - sn = va_arg(ap, char *); - percent = va_arg(ap, double); - va_end(ap); - - if (!sn || !(dim = oscar_direct_im_find(od, sn))) - return 1; - if (dim->watcher) { - gaim_input_remove(dim->watcher); /* Otherwise, the callback will callback */ - /* The callback will callback? I don't get how that would happen here. */ - dim->watcher = 0; - } - - dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, - oscar_callback, dim->conn); - - return 1; -} - -/* - * This is called after a direct IM has been received in its entirety. This - * function is passed a long chunk of data which contains the IM with any - * data chunks (images) appended to it. - * - * This function rips out all the data chunks and creates an imgstore for - * each one. In order to do this, it first goes through the IM and takes - * out all the IMG tags. When doing so, it rewrites the original IMG tag - * with one compatible with the imgstore Gaim core code. For each one, we - * then read in chunks of data from the end of the message and actually - * create the img store using the given data. - * - * For somewhat easy reference, here's a sample message - * (without the whitespace and asterisks): - * - * <HTML><BODY BGCOLOR="#ffffff"> - * <FONT LANG="0"> - * This is a really stupid picture:<BR> - * <IMG SRC="Sample.jpg" ID="1" WIDTH="283" HEIGHT="212" DATASIZE="9894"><BR> - * Yeah it is<BR> - * Here is another one:<BR> - * <IMG SRC="Soap Bubbles.bmp" ID="2" WIDTH="256" HEIGHT="256" DATASIZE="65978"> - * </FONT> - * </BODY></HTML> - * <BINARY> - * <DATA ID="1" SIZE="9894">datadatadatadata</DATA> - * <DATA ID="2" SIZE="65978">datadatadatadata</DATA> - * </BINARY> - */ -static int gaim_odc_incoming(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - GaimMessageFlags imflags = 0; - gchar *utf8; - GString *newmsg = g_string_new(""); - GSList *images = NULL; - va_list ap; - const char *sn, *msg, *msgend, *binary; - size_t len; - int encoding, isawaymsg; - - va_start(ap, fr); - sn = va_arg(ap, const char *); - msg = va_arg(ap, const char *); - len = va_arg(ap, size_t); - encoding = va_arg(ap, int); - isawaymsg = va_arg(ap, int); - va_end(ap); - msgend = msg + len; - - gaim_debug_info("oscar", "Got DirectIM message from %s\n", sn); - - if (isawaymsg) - imflags |= GAIM_MESSAGE_AUTO_RESP; - - /* message has a binary trailer */ - if ((binary = gaim_strcasestr(msg, "<binary>"))) { - GData *attribs; - const char *tmp, *start, *end, *last = NULL; - - tmp = msg; - - /* for each valid image tag... */ - while (gaim_markup_find_tag("img", tmp, &start, &end, &attribs)) { - const char *id, *src, *datasize; - const char *data = NULL; - char *tag = NULL; - size_t size; - int imgid = 0; - - /* update the location of the last img tag */ - last = end; - - /* grab attributes */ - id = g_datalist_get_data(&attribs, "id"); - src = g_datalist_get_data(&attribs, "src"); - datasize = g_datalist_get_data(&attribs, "datasize"); - - /* if we have id & datasize, build the data tag */ - if (id && datasize) - tag = g_strdup_printf("<data id=\"%s\" size=\"%s\">", id, datasize); - - /* if we have a tag, find the start of the data */ - if (tag && (data = gaim_strcasestr(binary, tag))) - data += strlen(tag); - - g_free(tag); - - /* check the data is here and store it */ - if (data + (size = atoi(datasize)) <= msgend) - imgid = gaim_imgstore_add(data, size, src); - - /* - * XXX - The code below contains some calls to oscar_encoding_to_utf8 - * The hardcoded "us-ascii" value REALLY needs to be removed. - */ - /* if we have a stored image... */ - if (imgid) { - /* append the message up to the tag */ - utf8 = oscar_encoding_to_utf8("us-ascii", tmp, start - tmp); - if (utf8 != NULL) { - newmsg = g_string_append(newmsg, utf8); - g_free(utf8); - } - - /* write the new image tag */ - g_string_append_printf(newmsg, "<IMG ID=\"%d\">", imgid); - - /* and record the image number */ - images = g_slist_append(images, GINT_TO_POINTER(imgid)); - } else { - /* otherwise, copy up to the end of the tag */ - utf8 = oscar_encoding_to_utf8("us-ascii", tmp, (end + 1) - tmp); - if (utf8 != NULL) { - newmsg = g_string_append(newmsg, utf8); - g_free(utf8); - } - } - - /* clear the attribute list */ - g_datalist_clear(&attribs); - - /* continue from the end of the tag */ - tmp = end + 1; - } - - /* append any remaining message data (without the > :-) */ - if (last++ && (last < binary)) - newmsg = g_string_append_len(newmsg, last, binary - last); - - /* set the flag if we caught any images */ - if (images) - imflags |= GAIM_MESSAGE_IMAGES; - } else { - g_string_append_len(newmsg, msg, len); - } - - /* Convert to UTF8 */ - /* (This hasn't been tested very much) */ - utf8 = gaim_plugin_oscar_decode_im_part(gc->account, sn, encoding, 0x0000, newmsg->str, len); - if (utf8 != NULL) { - serv_got_im(gc, sn, utf8, imflags, time(NULL)); - g_free(utf8); - } - - /* free the message */ - g_string_free(newmsg, TRUE); - - /* unref any images we allocated */ - if (images) { - GSList *tmp; - int id; - - for (tmp = images; tmp != NULL; tmp = tmp->next) { - id = GPOINTER_TO_INT(tmp->data); - gaim_imgstore_unref(id); - } - - g_slist_free(images); - } - - return 1; -} - -static int gaim_odc_typing(OscarSession *sess, FlapFrame *fr, ...) { - va_list ap; - char *sn; - int typing; - GaimConnection *gc = sess->aux_data; - - va_start(ap, fr); - sn = va_arg(ap, char *); - typing = va_arg(ap, int); - va_end(ap); - - if (typing == 0x0002) { - /* I had to leave this. It's just too funny. It reminds me of my sister. */ - gaim_debug_info("oscar", - "ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn); - serv_got_typing(gc, sn, 0, GAIM_TYPING); - } else if (typing == 0x0001) - serv_got_typing(gc, sn, 0, GAIM_TYPED); - else - serv_got_typing_stopped(gc, sn); - return 1; -} - -static int gaim_odc_send_im(OscarSession *sess, OscarConnection *conn, const char *message, GaimMessageFlags imflags) { - char *buf; - size_t len; - int ret; - GString *msg = g_string_new("<HTML><BODY>"); - GString *data = g_string_new("</BODY></HTML><BINARY>"); - GData *attribs; - const char *start, *end, *last; - int oscar_id = 0; - - last = message; - - /* for each valid IMG tag... */ - while (last && *last && gaim_markup_find_tag("img", last, &start, &end, &attribs)) { - GaimStoredImage *image = NULL; - const char *id; - - if (start - last) { - g_string_append_len(msg, last, start - last); - } - - id = g_datalist_get_data(&attribs, "id"); - - /* ... if it refers to a valid gaim image ... */ - if (id && (image = gaim_imgstore_get(atoi(id)))) { - /* ... append the message from start to the tag ... */ - unsigned long size = gaim_imgstore_get_size(image); - const char *filename = gaim_imgstore_get_filename(image); - gpointer imgdata = gaim_imgstore_get_data(image); - - oscar_id++; - - /* ... insert a new img tag with the oscar id ... */ - if (filename) - g_string_append_printf(msg, - "<IMG SRC=\"%s\" ID=\"%d\" DATASIZE=\"%lu\">", - filename, oscar_id, size); - else - g_string_append_printf(msg, - "<IMG ID=\"%d\" DATASIZE=\"%lu\">", - oscar_id, size); - - /* ... and append the data to the binary section ... */ - g_string_append_printf(data, "<DATA ID=\"%d\" SIZE=\"%lu\">", - oscar_id, size); - data = g_string_append_len(data, imgdata, size); - data = g_string_append(data, "</DATA>"); - } - /* If the tag is invalid, skip it, thus no else here */ - - g_datalist_clear(&attribs); - - /* continue from the end of the tag */ - last = end + 1; - } - - /* append any remaining message data (without the > :-) */ - if (last && *last) - msg = g_string_append(msg, last); - - /* if we inserted any images in the binary section, append it */ - if (oscar_id) { - msg = g_string_append_len(msg, data->str, data->len); - msg = g_string_append(msg, "</BINARY>"); - } - - len = msg->len; - buf = msg->str; - g_string_free(msg, FALSE); - g_string_free(data, TRUE); - - - /* XXX - The last parameter below is the encoding. Let Paco-Paco do something with it. */ - if (imflags & GAIM_MESSAGE_AUTO_RESP) - ret = aim_odc_send_im(sess, conn, buf, len, 0, 1); - else - ret = aim_odc_send_im(sess, conn, buf, len, 0, 0); - - g_free(buf); - - return ret; -} - -struct ask_do_dir_im { - char *who; - GaimConnection *gc; -}; - -static void oscar_cancel_direct_im(struct ask_do_dir_im *data) { - g_free(data->who); - g_free(data); -} - -struct dir_im_listen { - struct oscar_direct_im *dim; - const guchar *cookie; -}; + flap_connection_schedule_destroy(cc->conn); + oscar_chat_destroy(cc); +} static void -oscar_direct_im_listen_cb(int listenfd, gpointer data) { - struct dir_im_listen *dim_l = data; - const char *ip; - OscarData *od; - struct oscar_direct_im *dim = dim_l->dim; - - od = (OscarData *)dim->gc->proto_data; - - /* XXX: shouldn't this be your public IP or something? */ - ip = gaim_network_get_my_ip(od->conn ? od->conn->fd : -1); - - if (listenfd >= 0) - dim->conn = aim_odc_initiate(od->sess, dim->name, listenfd, - gaim_network_ip_atoi(ip), - gaim_network_get_port_from_fd(listenfd), dim_l->cookie); - - if (dim->conn != NULL) { - char *tmp; - GaimConversation *conv; - - od->direct_ims = g_slist_append(od->direct_ims, dim); - dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, - oscar_callback, dim->conn); - aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIM_ESTABLISHED, - gaim_odc_initiate, 0); - - conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, dim->gc->account, dim->name); - tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for Direct IM."), - dim->name, ip, gaim_network_get_port_from_fd(listenfd)); - gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); - g_free(tmp); - } else { - gaim_notify_error(dim->gc, NULL, _("Unable to open Direct IM"), NULL); - oscar_direct_im_destroy(od, dim); - } - - g_free(dim_l); -} - -/* this function is used to initiate a direct im session with someone. - * we start listening on a port and send a request. they either connect - * or send some kind of reply. If they can't connect, they ask us to - * connect to them, and so we do that. - * - * this function will also get called if the other side initiate's a direct - * im and we try to connect and fail. in that case cookie will not be null. - * - * note that cookie is an 8 byte string that isn't NULL terminated +destroy_new_conn_data(NewFlapConnectionData *new_conn_data) +{ + if ((new_conn_data->data != NULL) && + (new_conn_data->conn->type == SNAC_FAMILY_CHAT)) + { + oscar_chat_destroy(new_conn_data->data); + } + g_free(new_conn_data->cookie); + g_free(new_conn_data); +} + +/** + * This is the callback function anytime gaim_proxy_connect() + * establishes a new TCP connection with an oscar host. Depending + * on the type of host, we do a few different things here. */ -static void oscar_direct_im_initiate(GaimConnection *gc, const char *who, const guchar *cookie) { - OscarData *od; - struct oscar_direct_im *dim; - struct dir_im_listen *dim_l; - - od = (OscarData *)gc->proto_data; - - dim = oscar_direct_im_find(od, who); - if (dim) { - /* TODO: we need to somehow not do this if we're waiting - for the gaim_network_listen_range() call to finish */ - if (!(dim->connected)) { /* We'll free the old, unconnected dim, and start over */ - oscar_direct_im_disconnect(od, dim); - gaim_debug_info("oscar", - "Gave up on old direct IM, trying again\n"); - } else { - gaim_notify_error(gc, NULL, "DirectIM already open.", NULL); - return; - } - } - dim = g_new0(struct oscar_direct_im, 1); - dim->gc = gc; - g_snprintf(dim->name, sizeof dim->name, "%s", who); - - dim_l = g_new0(struct dir_im_listen, 1); - dim_l->dim = dim; - dim_l->cookie = cookie; - - if(!gaim_network_listen_range(5190, 5199, SOCK_STREAM, - oscar_direct_im_listen_cb, dim_l)) { - gaim_notify_error(gc, NULL, _("Unable to open Direct IM"), NULL); - oscar_direct_im_destroy(od, dim); - g_free(dim_l); - } -} - -static void oscar_direct_im(struct ask_do_dir_im *data) { - GaimConnection *gc = data->gc; - - if (!g_list_find(gaim_connections_get_all(), gc)) { - g_free(data->who); - g_free(data); - return; - } - - oscar_direct_im_initiate(gc, data->who, NULL); - g_free(data->who); - g_free(data); -} - -/* this is the right click menu cb thingy */ -static void oscar_ask_direct_im(GaimBlistNode *node, gpointer ignored) { - - GaimBuddy *buddy; - GaimConnection *gc; - gchar *buf; - struct ask_do_dir_im *data; - - g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); - - buddy = (GaimBuddy *) node; - gc = gaim_account_get_connection(buddy->account); - - data = g_new0(struct ask_do_dir_im, 1); - data->who = g_strdup(buddy->name); - data->gc = gc; - buf = g_strdup_printf(_("You have selected to open a Direct IM connection with %s."), - buddy->name); - - gaim_request_action(gc, NULL, buf, - _("Because this reveals your IP address, it " - "may be considered a privacy risk. Do you " - "wish to continue?"), - 0, data, 2, - _("_Connect"), G_CALLBACK(oscar_direct_im), - _("Cancel"), G_CALLBACK(oscar_cancel_direct_im)); - g_free(buf); -} - -/***************************************************************************** - * End scary direct im stuff - *****************************************************************************/ - static void -oscar_callback(gpointer data, gint source, GaimInputCondition condition) +connection_established_cb(gpointer data, gint source, GaimInputCondition cond) { - OscarConnection *conn; - OscarSession *sess; + NewFlapConnectionData *new_conn_data; GaimConnection *gc; OscarData *od; - - conn = (OscarConnection *)data; - sess = aim_conn_getsess(conn); - gc = sess ? sess->aux_data : NULL; - - if (gc == NULL) + FlapConnection *conn; + + new_conn_data = data; + gc = new_conn_data->gc; + + if (!g_list_find(gaim_connections_get_all(), gc)) { - gaim_debug_info("oscar", "oscar callback for closed connection (1).\n"); + if (source >= 0) + close(source); + destroy_new_conn_data(new_conn_data); return; } od = gc->proto_data; - if (od == NULL) - { - gaim_debug_warning("oscar","NULL od in oscar_callback; conn closed?\n"); - return; - } - - if (!g_list_find(gaim_connections_get_all(), gc)) + conn = new_conn_data->conn; + conn->fd = source; + + if (source < 0) { - /* oh boy. this is probably bad. i guess the only thing we - * can really do is return? */ - gaim_debug_info("oscar", - "oscar callback for closed connection (2).\n"); - gaim_debug_misc("oscar", "gc = %p\n", gc); - return; - } - - /* We only care about READ conditions */ - if (!(condition & GAIM_INPUT_READ)) + gaim_debug_error("oscar", "unable to connect FLAP server " + "of type 0x%04hx\n", conn->type); + if (conn->type == SNAC_FAMILY_AUTH) + gaim_connection_error(gc, _("Could not connect to authentication server")); + if (conn->type == SNAC_FAMILY_LOCATE) + gaim_connection_error(gc, _("Could not connect to BOS server")); + else /* Maybe we should call this for BOS connections, too? */ + flap_connection_schedule_destroy(conn); + destroy_new_conn_data(new_conn_data); return; - - if (conn->type == AIM_CONN_TYPE_LISTENER) { - gaim_debug_info("oscar", - "got information on rendezvous listener\n"); - if (aim_handlerendconnect(od->sess, conn) < 0) { - gaim_debug_error("oscar", - "connection error (rendezvous listener)\n"); - oscar_connection_destroy(od->sess, conn); - /* AAA - Don't we need to gaim_xfer_cancel here? --marv */ - } - } else { - if (aim_get_command(od->sess, conn) >= 0) { - aim_rxdispatch(od->sess); - if (od->killme) { - gaim_debug_error("oscar", "Waiting to be destroyed\n"); - return; - } - } else { - if ((conn->type == AIM_CONN_TYPE_BOS) || - !(aim_getconn_type(od->sess, AIM_CONN_TYPE_BOS))) - { - gaim_debug_error("oscar", "Major connection error " - "(invalid data was received on the oscar TCP stream).\n"); - gaim_connection_error(gc, _("Disconnected.")); - } else if (conn->type == AIM_CONN_TYPE_CHAT) { - struct chat_connection *cc = find_oscar_chat_by_conn(gc, conn); - GaimConversation *conv = gaim_find_chat(gc, cc->id); - char *buf; - gaim_debug_info("oscar", "Lost connection " - "to chat room %s\n", cc->name); - - buf = g_strdup_printf(_("You have lost your connection " - "to chat room %s."), cc->name); - if (conv != NULL) - gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_ERROR, time(NULL)); - else - gaim_notify_error(gc, NULL, buf, NULL); - g_free(buf); - - oscar_chat_kill(gc, cc); - - } else if (conn->type == AIM_CONN_TYPE_CHATNAV) { - if (od->cnpa > 0) - gaim_input_remove(od->cnpa); - od->cnpa = 0; - gaim_debug_info("oscar", - "removing chatnav input watcher\n"); - while (od->create_rooms) { - struct create_room *cr = od->create_rooms->data; - g_free(cr->name); - od->create_rooms = - g_slist_remove(od->create_rooms, cr); - g_free(cr); - gaim_notify_error(gc, NULL, - _("Chat is currently unavailable"), - NULL); - } - gaim_debug_info("oscar","killing rendezvous connection\n"); - oscar_connection_destroy(od->sess, conn); - } else if (conn->type == AIM_CONN_TYPE_AUTH) { - if (od->paspa > 0) - gaim_input_remove(od->paspa); - od->paspa = 0; - gaim_debug_info("oscar", - "removing authconn input watcher\n"); - oscar_connection_destroy(od->sess, conn); - } else if (conn->type == AIM_CONN_TYPE_EMAIL) { - if (od->emlpa > 0) - gaim_input_remove(od->emlpa); - od->emlpa = 0; - gaim_debug_info("oscar", - "removing email input watcher\n"); - oscar_connection_destroy(od->sess, conn); - } else if (conn->type == AIM_CONN_TYPE_ICON) { - if (od->icopa > 0) - gaim_input_remove(od->icopa); - od->icopa = 0; - gaim_debug_info("oscar", - "removing icon input watcher\n"); - oscar_connection_destroy(od->sess, conn); - } else if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) { - if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) - gaim_odc_disconnect(od->sess, conn); - gaim_debug_info("oscar","killing rendezvous connection\n"); - oscar_connection_destroy(od->sess, conn); - } else { - gaim_debug_error("oscar", - "holy crap! generic connection error! %hu\n", - conn->type); - oscar_connection_destroy(od->sess, conn); - } - } - } -} - -static void oscar_login_connect(gpointer data, gint source, GaimInputCondition cond) + } + + gaim_debug_info("oscar", "connected to FLAP server of type 0x%04hx\n", + conn->type); + conn->watcher_incoming = gaim_input_add(conn->fd, + GAIM_INPUT_READ, flap_connection_recv_cb, conn); + if (new_conn_data->cookie == NULL) + flap_connection_send_version(od, conn); + else + flap_connection_send_version_with_cookie(od, conn, + new_conn_data->cookielen, new_conn_data->cookie); + + if (conn->type == SNAC_FAMILY_AUTH) + { + GaimAccount *account; + account = gaim_connection_get_account(gc); + aim_request_login(od, conn, gaim_account_get_username(account)); + gaim_debug_info("oscar", "Screen name sent, waiting for response\n"); + gaim_connection_update_progress(gc, _("Screen name sent"), 1, OSCAR_CONNECT_STEPS); + ck[1] = 0x65; + } + else if (conn->type == SNAC_FAMILY_LOCATE) + { + gaim_connection_update_progress(gc, _("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS); + ck[4] = 0x61; + } + else if (conn->type == SNAC_FAMILY_CHAT) + { + od->oscar_chats = g_slist_append(od->oscar_chats, new_conn_data->data); + new_conn_data->data = NULL; + } + + destroy_new_conn_data(new_conn_data); +} + +static void +flap_connection_established_bos(OscarData *od, FlapConnection *conn) +{ + GaimConnection *gc = od->gc; + + aim_reqpersonalinfo(od, conn); + + gaim_debug_info("oscar", "ssi: requesting rights and list\n"); + aim_ssi_reqrights(od); + aim_ssi_reqdata(od); + if (od->getblisttimer > 0) + gaim_timeout_remove(od->getblisttimer); + od->getblisttimer = gaim_timeout_add(30000, gaim_ssi_rerequestdata, od); + + aim_locate_reqrights(od); + aim_buddylist_reqrights(od, conn); + aim_im_reqparams(od); + aim_bos_reqrights(od, conn); /* TODO: Don't call this with ssi */ + + gaim_connection_update_progress(gc, _("Finalizing connection"), 5, OSCAR_CONNECT_STEPS); +} + +static void +flap_connection_established_admin(OscarData *od, FlapConnection *conn) { - GaimConnection *gc = data; - OscarData *od; - OscarSession *sess; - OscarConnection *conn; - - if (!g_list_find(gaim_connections_get_all(), gc)) { - close(source); - return; - } - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - - od = gc->proto_data; - sess = od->sess; - conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH); - conn->fd = source; - - if (source < 0) { - gaim_connection_error(gc, _("Couldn't connect to host")); - return; - } - - aim_conn_completeconnect(sess, conn); - gc->inpa = gaim_input_add(conn->fd, GAIM_INPUT_READ, oscar_callback, conn); - aim_request_login(sess, conn, gaim_account_get_username(gaim_connection_get_account(gc))); - - gaim_debug_info("oscar", - "Screen name sent, waiting for response\n"); - gaim_connection_update_progress(gc, _("Screen name sent"), 1, OSCAR_CONNECT_STEPS); - ck[1] = 0x65; + aim_clientready(od, conn); + gaim_debug_info("oscar", "connected to admin\n"); + + if (od->chpass) { + gaim_debug_info("oscar", "changing password\n"); + aim_admin_changepasswd(od, conn, od->newp, od->oldp); + g_free(od->oldp); + od->oldp = NULL; + g_free(od->newp); + od->newp = NULL; + od->chpass = FALSE; + } + if (od->setnick) { + gaim_debug_info("oscar", "formatting screen name\n"); + aim_admin_setnick(od, conn, od->newsn); + g_free(od->newsn); + od->newsn = NULL; + od->setnick = FALSE; + } + if (od->conf) { + gaim_debug_info("oscar", "confirming account\n"); + aim_admin_reqconfirm(od, conn); + od->conf = FALSE; + } + if (od->reqemail) { + gaim_debug_info("oscar", "requesting e-mail address\n"); + aim_admin_getinfo(od, conn, 0x0011); + od->reqemail = FALSE; + } + if (od->setemail) { + gaim_debug_info("oscar", "setting e-mail address\n"); + aim_admin_setemail(od, conn, od->email); + g_free(od->email); + od->email = NULL; + od->setemail = FALSE; + } +} + +static void +flap_connection_established_chat(OscarData *od, FlapConnection *conn) +{ + GaimConnection *gc = od->gc; + struct chat_connection *chatcon; + static int id = 1; + + aim_clientready(od, conn); + + chatcon = find_oscar_chat_by_conn(gc, conn); + chatcon->id = id; + chatcon->conv = serv_got_joined_chat(gc, id++, chatcon->show); +} + +static void +flap_connection_established_chatnav(OscarData *od, FlapConnection *conn) +{ + aim_clientready(od, conn); + aim_chatnav_reqrights(od, conn); +} + +static void +flap_connection_established_alert(OscarData *od, FlapConnection *conn) +{ + aim_email_sendcookies(od); + aim_email_activate(od); + aim_clientready(od, conn); +} + +static void +flap_connection_established_bart(OscarData *od, FlapConnection *conn) +{ + GaimConnection *gc = od->gc; + + aim_clientready(od, conn); + + od->iconconnecting = FALSE; + + if (od->icontimer) + gaim_timeout_remove(od->icontimer); + od->icontimer = gaim_timeout_add(100, gaim_icon_timerfunc, gc); +} + +static int +flap_connection_established(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) +{ + gaim_debug_info("oscar", "FLAP connection of type 0x%04hx is " + "now fully connected\n", conn->type); + if (conn->type == SNAC_FAMILY_LOCATE) + flap_connection_established_bos(od, conn); + else if (conn->type == SNAC_FAMILY_ADMIN) + flap_connection_established_admin(od, conn); + else if (conn->type == SNAC_FAMILY_CHAT) + flap_connection_established_chat(od, conn); + else if (conn->type == SNAC_FAMILY_CHATNAV) + flap_connection_established_chatnav(od, conn); + else if (conn->type == SNAC_FAMILY_ALERT) + flap_connection_established_alert(od, conn); + else if (conn->type == SNAC_FAMILY_BART) + flap_connection_established_bart(od, conn); + + return 1; } static void oscar_login(GaimAccount *account) { - OscarSession *sess; - OscarConnection *conn; - GaimConnection *gc = gaim_account_get_connection(account); - OscarData *od = gc->proto_data = g_new0(OscarData, 1); + GaimConnection *gc; + OscarData *od; + NewFlapConnectionData *new_conn_data; + + gc = gaim_account_get_connection(account); + od = gc->proto_data = oscar_data_new(); + od->gc = gc; + + oscar_data_addhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); + oscar_data_addhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, flap_connection_established, 0); + + oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0003, gaim_info_change, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0005, gaim_info_change, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0007, gaim_account_confirm, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ALERT, 0x0001, gaim_parse_genericerr, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ALERT, SNAC_SUBTYPE_ALERT_MAILSTATUS, gaim_email_parseupdate, 0); + oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0003, gaim_parse_auth_resp, 0); + oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0007, gaim_parse_login, 0); + oscar_data_addhandler(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_REQUEST, gaim_parse_auth_securid_request, 0); + oscar_data_addhandler(od, SNAC_FAMILY_BART, SNAC_SUBTYPE_BART_ERROR, gaim_icon_error, 0); + oscar_data_addhandler(od, SNAC_FAMILY_BART, SNAC_SUBTYPE_BART_RESPONSE, gaim_icon_parseicon, 0); + oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0001, gaim_parse_genericerr, 0); + oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0003, gaim_bosrights, 0); + oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, 0x0001, gaim_parse_genericerr, 0); + oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_RIGHTSINFO, gaim_parse_buddyrights, 0); + oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_ONCOMING, gaim_parse_oncoming, 0); + oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_OFFGOING, gaim_parse_offgoing, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHAT, 0x0001, gaim_parse_genericerr, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERJOIN, gaim_conv_chat_join, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERLEAVE, gaim_conv_chat_leave, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_ROOMINFOUPDATE, gaim_conv_chat_info_update, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_INCOMINGMSG, gaim_conv_chat_incoming_msg, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, 0x0001, gaim_parse_genericerr, 0); + oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, SNAC_SUBTYPE_CHATNAV_INFO, gaim_chatnav_info, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ERROR, gaim_ssi_parseerr, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO, gaim_ssi_parserights, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_LIST, gaim_ssi_parselist, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_NOLIST, gaim_ssi_parselist, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SRVACK, gaim_ssi_parseack, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADD, gaim_ssi_parseadd, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTH, gaim_ssi_authgiven, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ, gaim_ssi_authrequest, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP, gaim_ssi_authreply, 0); + oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADDED, gaim_ssi_gotadded, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICBM, 0x0005, gaim_icbm_param_info, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_INCOMING, gaim_parse_incoming_im, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MISSEDCALL, gaim_parse_misses, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_CLIENTAUTORESP, gaim_parse_clientauto, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_ERROR, gaim_parse_msgerr, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MTN, gaim_parse_mtn, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_ACK, gaim_parse_msgack, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_OFFLINEMSG, gaim_offlinemsg, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE, gaim_offlinemsgdone, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_ALIAS, gaim_icqalias, 0); + oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_INFO, gaim_icqinfo, 0); + oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_RIGHTSINFO, gaim_parse_locaterights, 0); + oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_USERINFO, gaim_parse_userinfo, 0); + oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_ERROR, gaim_parse_locerr, 0); + oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK, gaim_got_infoblock, 0); + oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0001, gaim_parse_genericerr, 0); + oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x000f, gaim_selfinfo, 0); + oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x001f, gaim_memrequest, 0); + oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0021, oscar_icon_req,0); + oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_RATECHANGE, gaim_parse_ratechange, 0); + oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_REDIRECT, gaim_handle_redirect, 0); + oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_MOTD, gaim_parse_motd, 0); + oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_EVIL, gaim_parse_evilnotify, 0); + oscar_data_addhandler(od, SNAC_FAMILY_POPUP, 0x0002, gaim_popup, 0); + oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, SNAC_SUBTYPE_USERLOOKUP_ERROR, gaim_parse_searcherror, 0); + oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, 0x0003, gaim_parse_searchreply, 0); gaim_debug_misc("oscar", "oscar_login: gc = %p\n", gc); @@ -1901,36 +1221,21 @@ gc->flags |= GAIM_CONNECTION_HTML; gc->flags |= GAIM_CONNECTION_AUTO_RESP; } - od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, oscar_free_buddyinfo); - - sess = oscar_session_new(); - /* - * We need an immediate queue because we don't use a while-loop - * to see if things need to be sent. - */ - aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL); - od->sess = sess; - sess->aux_data = gc; /* Connect to core Gaim signals */ gaim_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_cb, gc); - conn = oscar_connection_new(sess, AIM_CONN_TYPE_AUTH); - if (conn == NULL) { - gaim_debug_error("oscar", "internal connection error\n"); - gaim_connection_error(gc, _("Unable to login to AIM")); - return; - } - - aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); - aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); - aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); - aim_conn_addhandler(sess, conn, OSCAR_FAMILY_AUTH, OSCAR_SUBTYPE_AUTH_SECURID_REQUEST, gaim_parse_auth_securid_request, 0); - - conn->status |= AIM_CONN_STATUS_INPROGRESS; - if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER), - gaim_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), - oscar_login_connect, gc) < 0) { + new_conn_data = g_new(NewFlapConnectionData, 1); + new_conn_data->gc = gc; + new_conn_data->conn = flap_connection_new(od, SNAC_FAMILY_AUTH); + new_conn_data->cookielen = 0; + new_conn_data->cookie = NULL; + + if (gaim_proxy_connect(account, + gaim_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER), + gaim_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), + connection_established_cb, new_conn_data) < 0) + { gaim_connection_error(gc, _("Couldn't connect to host")); return; } @@ -1939,34 +1244,23 @@ ck[0] = 0x5a; } -static void oscar_close(GaimConnection *gc) { +/* TODO: Move most of this to oscar_data_destroy() */ +static void +oscar_close(GaimConnection *gc) +{ OscarData *od = (OscarData *)gc->proto_data; - while (od->oscar_chats) { - struct chat_connection *n = od->oscar_chats->data; - if (n->inpa > 0) - gaim_input_remove(n->inpa); - g_free(n->name); - g_free(n->show); - od->oscar_chats = g_slist_remove(od->oscar_chats, n); - g_free(n); - } - while (od->direct_ims) { - struct oscar_direct_im *n = od->direct_ims->data; - oscar_direct_im_destroy(od, n); - } -/* BBB */ - while (od->file_transfers) { - GaimXfer *xfer; - xfer = (GaimXfer *)od->file_transfers->data; - gaim_xfer_cancel_local(xfer); + while (od->oscar_chats) + { + struct chat_connection *cc = od->oscar_chats->data; + od->oscar_chats = g_slist_remove(od->oscar_chats, cc); + oscar_chat_destroy(cc); } while (od->requesticon) { - char *sn = od->requesticon->data; + gchar *sn = od->requesticon->data; od->requesticon = g_slist_remove(od->requesticon, sn); - free(sn); - } - g_hash_table_destroy(od->buddyinfo); + g_free(sn); + } while (od->create_rooms) { struct create_room *cr = od->create_rooms->data; g_free(cr->name); @@ -1979,16 +1273,6 @@ g_free(od->newp); if (od->oldp) g_free(od->oldp); - if (gc->inpa > 0) - gaim_input_remove(gc->inpa); - if (od->cnpa > 0) - gaim_input_remove(od->cnpa); - if (od->paspa > 0) - gaim_input_remove(od->paspa); - if (od->emlpa > 0) - gaim_input_remove(od->emlpa); - if (od->icopa > 0) - gaim_input_remove(od->icopa); if (od->icontimer > 0) gaim_timeout_remove(od->icontimer); if (od->getblisttimer > 0) @@ -1997,894 +1281,19 @@ gaim_timeout_remove(od->getinfotimer); gaim_prefs_disconnect_by_handle(gc); - oscar_session_destroy(od->sess); - od->sess = NULL; - g_free(gc->proto_data); + oscar_data_destroy(od); gc->proto_data = NULL; gaim_debug_info("oscar", "Signed off.\n"); } -static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition cond) { - GaimConnection *gc = data; - OscarData *od; - OscarSession *sess; - OscarConnection *bosconn; - - if (!g_list_find(gaim_connections_get_all(), gc)) { - close(source); - return; - } - - od = gc->proto_data; - sess = od->sess; - bosconn = od->conn; - bosconn->fd = source; - - if (source < 0) { - gaim_connection_error(gc, _("Could Not Connect")); - return; - } - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - - aim_conn_completeconnect(sess, bosconn); - gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn); - - gaim_connection_update_progress(gc, - _("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS); - ck[4] = 0x61; -} - -/* BBB */ -/* - * This little area in oscar.c is the nexus of file transfer code, - * so I wrote a little explanation of what happens. I am such a - * ninja. - * - * The series of events for a file send is: - * -Create xfer and call gaim_xfer_request (this happens in oscar_ask_sendfile) - * -User chooses a file and oscar_xfer_init is called. It establishes a - * listening socket, then asks the remote user to connect to us (and - * gives them the file name, port, IP, etc.) - * -They connect to us and we send them an PEER_TYPE_PROMPT (this happens - * in oscar_sendfile_estblsh) - * -They send us an PEER_TYPE_ACK and then we start sending data - * -When we finish, they send us an PEER_TYPE_DONE and they close the - * connection. - * -We get drunk because file transfer kicks ass. - * - * The series of events for a file receive is: - * -Create xfer and call gaim_xfer request (this happens in incomingim_chan2) - * -Gaim user selects file to name and location to save file to and - * oscar_xfer_init is called - * -It connects to the remote user using the IP they gave us earlier - * -After connecting, they send us an PEER_TYPE_PROMPT. In reply, we send - * them an PEER_TYPE_ACK. - * -They begin to send us lots of raw data. - * -When they finish sending data we send an PEER_TYPE_DONE and then close - * the connection. - * - * Update August 2005: - * The series of events for transfers has been seriously complicated by the addition - * of transfer redirects and proxied connections. I could throw a whole lot of words - * at trying to explain things here, but it probably wouldn't do much good. To get - * a better idea of what happens, take a look at the diagrams and documentation - * from my Summer of Code project. -- Jonathan Clark - */ -static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition); -static void oscar_xfer_proxylogin(gpointer data, gint source, GaimInputCondition condition); -static void oscar_send_file_request(GaimXfer *xfer); - -/* - * Miscellaneous xfer functions - */ -static GaimXfer *oscar_find_xfer_by_cookie(GSList *fts, const guint8 *ck) -{ - GaimXfer *xfer; - PeerConnection *peer_connection; - - while (fts) { - xfer = fts->data; - peer_connection = xfer->data; - - if (peer_connection && !memcmp(ck, peer_connection->cookie, 8)) - return xfer; - - fts = g_slist_next(fts); - } - - return NULL; -} - -static GaimXfer *oscar_find_xfer_by_conn(GSList *fts, OscarConnection *conn) -{ - GaimXfer *xfer; - PeerConnection *peer_connection; - - while (fts) { - xfer = fts->data; - peer_connection = xfer->data; - - if (peer_connection && (conn == peer_connection->conn)) - return xfer; - - fts = g_slist_next(fts); - } - - return NULL; -} - -/* - * We're done sending/receiving raw data through the connection. - * If we're the receiver, send an OFT header with the bytes received - * filled in to indicate this party's over. - */ -static void oscar_xfer_end(GaimXfer *xfer) -{ - PeerConnection *peer_connection = xfer->data; - GaimConnection *gc = peer_connection->sess->aux_data; - OscarData *od = gc->proto_data; - - gaim_debug_info("oscar", "AAA - in oscar_xfer_end\n"); - - if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { - peer_connection->fh.nrecvd = gaim_xfer_get_bytes_sent(xfer); - aim_oft_sendheader(peer_connection->sess, PEER_TYPE_DONE, peer_connection); - } - - oscar_connection_destroy(peer_connection->sess, peer_connection->conn); - aim_oft_destroyinfo(peer_connection); - xfer->data = NULL; - od->file_transfers = g_slist_remove(od->file_transfers, xfer); -} - -/* - * xfer functions used when receiving files - */ - -/* - * This is a gaim timeout callback called X milliseconds after a connection is attempted - * By this point, we've lost faith in the connection method we just tried and want to - * try something new. Hopefully, that new connection method will be more successful, - * otherwise, we'll end up here again and again until the connection is successful - * or we've tried every method... if that happens we just throw our hands up - * and inform the user of his bad karma. -*/ -static gboolean oscar_xfer_ip_timeout(gpointer data) { - GaimXfer *xfer; - GaimAccount *account; - PeerConnection *peer_connection; - char *msg = NULL; - - gaim_debug_info("oscar","AAA - in oscar_xfer_ip_timeout\n"); - - xfer = (GaimXfer*) data; - account = gaim_xfer_get_account(xfer); - if(xfer->data) { - peer_connection = (PeerConnection*) xfer->data; - - /* Check to see if the clientip has produced any results */ - if(!peer_connection->success) { - /* This connection has worn out its welcome. Goodbye. */ - if(peer_connection->conn) { - close(peer_connection->conn->fd); - oscar_connection_destroy(peer_connection->sess, peer_connection->conn); - } - - if(peer_connection->method == AIM_XFER_DIRECT || peer_connection->method == AIM_XFER_REDIR) { - /* If (we're currently using the verified ip) - * In case clientip & verifiedip are the same, - * we must prevent an infinite loop */ - if(xfer->remote_ip && peer_connection->verifiedip - && g_ascii_strcasecmp(xfer->remote_ip, peer_connection->verifiedip) == 0 - && g_ascii_strcasecmp(peer_connection->clientip, peer_connection->verifiedip) != 0 ) - { - /* The verifiedip timed out */ - if (peer_connection->method == AIM_XFER_DIRECT && !peer_connection->redir_attempted) - { - /* clientip & verifiedip failed, request a redirect - * that is, we want the sender to connect to us - * - * Above, we checked if we had previously attempted a connection - * redirect to prevent a conflict with the joscar library - */ - - /* Let the user not to lose hope quite yet*/ - msg = g_strdup_printf(_("Attempting connection redirect...")); - gaim_xfer_conversation_write(xfer, msg, FALSE); - g_free(msg); - - gaim_timeout_add(FT_REDIR_TIMEOUT, - oscar_xfer_ip_timeout, xfer); - peer_connection->method = AIM_XFER_REDIR; - peer_connection->redir_attempted = TRUE; - g_free(peer_connection->proxyip); - peer_connection->proxyip = NULL; - peer_connection->clientip = g_strdup( gaim_network_get_my_ip( - peer_connection->conn ? peer_connection->conn->fd : -1)); - oscar_xfer_init_send(xfer); - } else { - /* clientip, verifiedip, and redirect all failed. */ - gaim_debug_info("oscar", - "redirect timed out. requesting stg3 proxy\n"); - - /* Kill our listener */ - gaim_input_remove(xfer->watcher); - oscar_connection_destroy(peer_connection->sess, peer_connection->conn); - - /* Instead of failing here, request a stage 3 proxy */ - g_free(peer_connection->clientip); - g_free(peer_connection->verifiedip); - peer_connection->clientip = NULL; - peer_connection->verifiedip = NULL; - peer_connection->port = 0; - peer_connection->conn->type = AIM_CONN_TYPE_RENDEZVOUS; - peer_connection->method = AIM_XFER_PROXY; - peer_connection->stage = AIM_XFER_PROXY_STG3; - - aim_im_sendch2_sendfile_ask(peer_connection->sess, peer_connection); - } - } else { - /* clientip timed out, now try verifiedip */ - g_free(xfer->remote_ip); - xfer->remote_ip = g_strdup(peer_connection->verifiedip); - gaim_debug_info("oscar","attempting connection using verifiedip\n"); - oscar_xfer_init_recv(xfer); - } - } else if(peer_connection->method == AIM_XFER_PROXY) { - /* proxyip timed out - * Yes, it's a bit odd to ask the user to enable proxied file transfers - * when it's a proxied transfer that timed out. It is possible that a - * stage 1 or 2 proxied transfer might work when a stage 3 will not. */ - msg = g_strdup_printf(_("Transfer of file %s timed out.\n Try enabling proxy servers for file transfers in Accounts -> %s -> Edit Account -> Advanced."), - gaim_xfer_get_filename(xfer), gaim_account_get_username(account)); - gaim_xfer_conversation_write(xfer, msg, TRUE); - g_free(msg); - gaim_xfer_cancel_local(xfer); - if(peer_connection->xfer_reffed) { - peer_connection->xfer_reffed = FALSE; - gaim_xfer_unref(xfer); - } - } else { - gaim_debug_warning("oscar","unknown xfer method encountered in timout\n"); - } - } else { - if(peer_connection->xfer_reffed) { - peer_connection->xfer_reffed = FALSE; - gaim_xfer_unref(xfer); - } - gaim_debug_info("oscar","connection successful; timeout off\n"); - } - } else { - gaim_debug_info("oscar","transfer already done; nothing to do\n"); - } - return FALSE; -} - -/* - * Connect to another client or a file transfer proxy server. - * Though this function has traditionally only been used during file receives, - * it is now called to make any sort of file transfer connection via gaim_proxy_connect. - */ -static void oscar_xfer_init_recv(GaimXfer *xfer) -{ - PeerConnection *peer_connection; - PeerProxyInfo *proxy_info; - GaimConnection *gc; - OscarData *od; - GaimInputFunction nextstop_cb; - int rc; - - g_return_if_fail(xfer != NULL); - g_return_if_fail(xfer->data != NULL); - - peer_connection = xfer->data; - proxy_info = peer_connection->proxy_info; - gc = peer_connection->sess->aux_data; - od = gc->proto_data; - - gaim_debug_info("oscar", "AAA - in oscar_xfer_init_recv\n"); - - /* Start a timer for this ip address - * If the clientip fails, try the verifiedip - * If that fails, wait for the transfer to redirect - * This xfer reference will be released in oscar_xfer_ip_timeout */ - if(!peer_connection->xfer_reffed) { - peer_connection->xfer_reffed = TRUE; - gaim_xfer_ref(xfer); - } - - if(peer_connection->method != AIM_XFER_PROXY) { - /* If (we're currently using the verified ip) - * In case clientip & verifiedip are the same, we must prevent an infinite loop */ - if(xfer->remote_ip && peer_connection->verifiedip - && g_ascii_strcasecmp(xfer->remote_ip, peer_connection->verifiedip) == 0 - && g_ascii_strcasecmp(peer_connection->clientip, peer_connection->verifiedip) != 0 ) { - gaim_timeout_add(FT_VERIFIEDIP_TIMEOUT, oscar_xfer_ip_timeout, xfer); - } else { - gaim_timeout_add(FT_CLIENTIP_TIMEOUT, oscar_xfer_ip_timeout, xfer); - } - } else { - gaim_timeout_add(FT_PROXYIP_TIMEOUT, oscar_xfer_ip_timeout, xfer); - } - peer_connection->conn = oscar_connection_new(od->sess, AIM_CONN_TYPE_RENDEZVOUS); - - /* If we're routing this transfer through a AOL proxy server, do the special login - * before telling the other client we're ready for action. - * Note, firststop_cb is the first function called after gaim has made a connection - * Also, the connection type is changed until the proxy login is complete */ - if(peer_connection->method == AIM_XFER_PROXY) { - if(proxy_info) - proxy_info->conn = peer_connection->conn; - else { - gaim_debug_warning("oscar","NULL proxy_info\n"); - gaim_xfer_cancel_local(xfer); - } - nextstop_cb = oscar_xfer_proxylogin; - peer_connection->conn->type = AIM_CONN_TYPE_RENDEZVOUS_PROXY; - } else { - nextstop_cb = oscar_sendfile_connected; - } - - if (peer_connection->conn) { - peer_connection->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; - aim_conn_addhandler(od->sess, peer_connection->conn, AIM_CB_FAM_OFT, PEER_TYPE_PROMPT, - oscar_sendfile_prompt, 0); - rc = gaim_proxy_connect(gaim_connection_get_account(gc), - xfer->remote_ip, xfer->remote_port, nextstop_cb, xfer); - if (rc == -1) { - gaim_xfer_error(GAIM_XFER_RECEIVE, gaim_xfer_get_account(xfer), xfer->who, - _("Unable to establish file descriptor.")); - gaim_xfer_cancel_local(xfer); - } - } else { - gaim_xfer_error(GAIM_XFER_RECEIVE, gaim_xfer_get_account(xfer), xfer->who, - _("Unable to create new connection.")); - gaim_xfer_cancel_local(xfer); - /* Try a different port? Ask them to connect to us? /join #gaim and whine? */ - } -} - -/* - * "Never mind. This transfer wasn't such a great idea after all." - */ -static void oscar_xfer_cancel_recv(GaimXfer *xfer) -{ - PeerConnection *peer_connection = xfer->data; - GaimConnection *gc = peer_connection->sess->aux_data; - OscarData *od = gc->proto_data; - - gaim_debug_info("oscar", "AAA - in oscar_xfer_cancel_recv\n"); - - if (gaim_xfer_get_status(xfer) != GAIM_XFER_STATUS_CANCEL_REMOTE) - aim_im_sendch2_sendfile_cancel(peer_connection->sess, peer_connection); - - if(peer_connection->sess && peer_connection->conn) - oscar_connection_destroy(peer_connection->sess, peer_connection->conn); - aim_oft_destroyinfo(peer_connection); - xfer->data = NULL; - od->file_transfers = g_slist_remove(od->file_transfers, xfer); -} - -/* - * Called after every data packet we receive - */ -static void oscar_xfer_ack_recv(GaimXfer *xfer, const guchar *buffer, size_t size) +static int +gaim_parse_auth_resp(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - PeerConnection *peer_connection = xfer->data; - - /* Update our rolling checksum. Like Walmart, yo. */ - peer_connection->fh.recvcsum = aim_oft_checksum_chunk(buffer, size, peer_connection->fh.recvcsum); -} - -/* - * xfer functions used for proxied file transfers - */ - -/* - * Called by oscar_send_proxylogin_cb when we receive a ready packet - * BBB - */ -static void oscar_xfer_proxylogin_ready(GaimXfer *xfer, gint fd) { - PeerConnection *peer_connection; - PeerProxyInfo *proxy_info; - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(fd, F_SETFL, 0); - - gaim_debug_info("oscar","AAA - in oscar_xfer_proxylogin_ready\n"); - if (!(peer_connection = xfer->data)) { - gaim_debug_warning("oscar","NULL peer_connection; aborting\n"); - gaim_xfer_cancel_local(xfer); - return; - } - if (!(proxy_info = peer_connection->proxy_info)) { - gaim_debug_warning("oscar","NULL proxy_info; aborting\n"); - gaim_xfer_cancel_local(xfer); - return; - } - - /* Remove the rv proxy watcher and put the connection type back the way we found it */ - gaim_input_remove(xfer->watcher); - xfer->watcher = 0; - peer_connection->conn->type = AIM_CONN_TYPE_RENDEZVOUS; - - if(peer_connection->send_or_recv == AIM_XFER_SEND) { - - if(peer_connection->stage == AIM_XFER_PROXY_STG2) { - aim_im_sendch2_sendfile_accept(peer_connection->sess, peer_connection); - - /* For stage 2, both file headers are filled in */ - memcpy(&peer_connection->fh.bcookie, peer_connection->cookie, 8); - } - - /* The following is taken from oscar_sendfile_estblsh */ - aim_conn_addhandler(peer_connection->sess, peer_connection->conn, AIM_CB_FAM_OFT, PEER_TYPE_ACK, - oscar_sendfile_ack, 0); - aim_conn_addhandler(peer_connection->sess, peer_connection->conn, AIM_CB_FAM_OFT, PEER_TYPE_DONE, - oscar_sendfile_done, 0); - xfer->watcher = gaim_input_add(peer_connection->conn->fd, GAIM_INPUT_READ, oscar_callback, - peer_connection->conn); - - /* Inform the other user that we are connected and ready to transfer */ - aim_oft_sendheader(peer_connection->sess, PEER_TYPE_PROMPT, peer_connection); - } else if(peer_connection->send_or_recv == AIM_XFER_RECV) { - oscar_sendfile_connected(xfer, fd, GAIM_INPUT_READ); - } else { - gaim_debug_warning("oscar","no value for send_or_recv; aborting transfer\n"); - gaim_xfer_cancel_local(xfer); - } -} - -/* - * Called by oscar_sendfile_proxylogin_cb when we receive an ack packet in reply to an init_send - * BBB - */ -static void oscar_xfer_proxylogin_ack(GaimXfer *xfer) { - PeerConnection *peer_connection; - PeerProxyInfo *proxy_info; - - gaim_debug_info("oscar","AAA - in oscar_xfer_proxylogin_ack\n"); - if (!(peer_connection = xfer->data)) { - gaim_debug_warning("oscar","NULL peer_connection; aborting\n"); - gaim_xfer_cancel_local(xfer); - return; - } - if (!(proxy_info = peer_connection->proxy_info)) { - gaim_debug_warning("oscar","NULL proxy_info; aborting\n"); - gaim_xfer_cancel_local(xfer); - return; - } - - /* Use the proxy "port" we just ACK-quired (hah) so that the proxy will love us */ - peer_connection->port = proxy_info->port; - peer_connection->proxyip = g_strdup(proxy_info->ip); - gaim_debug_info("oscar","received client ip and port: %s:%d\n", - peer_connection->proxyip, peer_connection->port); - - if(peer_connection->send_or_recv == AIM_XFER_SEND) { - oscar_send_file_request(xfer); - } else if(peer_connection->send_or_recv == AIM_XFER_RECV) { - strncpy(peer_connection->fh.name, xfer->filename, 64); - peer_connection->fh.name[63] = '\0'; - peer_connection->fh.totsize = gaim_xfer_get_size(xfer); - peer_connection->fh.size = gaim_xfer_get_size(xfer); - - /* Calculating the checksum can take a very long time for large files */ - gaim_debug_info("oscar","calculating file checksum\n"); - peer_connection->fh.checksum = aim_oft_checksum_file(xfer->local_filename); - gaim_debug_info("oscar","checksum calculated\n"); - - aim_im_sendch2_sendfile_ask(peer_connection->sess, peer_connection); - } else { - gaim_debug_warning("oscar","no value for send_or_recv; aborting transfer\n"); - gaim_xfer_cancel_local(xfer); - } -} - -/* - * This is called whenever we receive data while negotiating a rendezvous proxy connection - * BBB - */ -static void oscar_xfer_proxylogin_cb(gpointer data, gint source, GaimInputCondition condition) { - GaimXfer *xfer; - PeerConnection *peer_connection; - - gaim_debug_info("oscar","AAA - in oscar_xfer_proxylogin_cb\n"); - if (!(xfer = data)) { - gaim_debug_warning("oscar","NULL xfer; aborting\n"); - gaim_xfer_cancel_local(xfer); - return; - } - if (!(peer_connection = xfer->data)) { - gaim_debug_warning("oscar","NULL peer_connection; aborting\n"); - gaim_xfer_cancel_local(xfer); - return; - } - - if( (peer_connection->proxy_info = aim_rv_proxy_read(peer_connection->sess, peer_connection->conn)) ) { - - switch(peer_connection->proxy_info->cmd_type) { - case AIM_RV_PROXY_READY: - oscar_xfer_proxylogin_ready(xfer, source); - free(peer_connection->proxy_info); - peer_connection->proxy_info = NULL; - break; - case AIM_RV_PROXY_ACK: - oscar_xfer_proxylogin_ack(xfer); - free(peer_connection->proxy_info); - peer_connection->proxy_info = NULL; - break; - case AIM_RV_PROXY_ERROR: - gaim_debug_info("oscar","error logging into rendezvous proxy; err code is %x\n", - peer_connection->proxy_info->err_code); - gaim_input_remove(xfer->watcher); - xfer->watcher = 0; - free(peer_connection->proxy_info); - peer_connection->proxy_info = NULL; - gaim_xfer_cancel_remote(xfer); - break; - /* We should never get here */ - default: - gaim_debug_info("oscar","proxylogin switch defaulted unexpectedly\n"); - } - } else { - gaim_debug_info("oscar","could not read rv proxy packet\n"); - } -} - -/* - * Called to send necessary login data to a rendezvous proxy server once we're connected - * Takes xfer is data and fd as source - */ -static void oscar_xfer_proxylogin(gpointer data, gint source, GaimInputCondition condition) -{ - GaimXfer *xfer; - PeerConnection *peer_connection; - PeerProxyInfo *proxy_info; - int err; - - gaim_debug_info("oscar","AAA - in oscar_xfer_proxylogin\n"); - if (!(xfer = data)) { - gaim_debug_warning("oscar","NULL xfer; aborting\n"); - gaim_xfer_cancel_local(xfer); - return; - } - if (!(peer_connection = xfer->data)) { - gaim_debug_warning("oscar","NULL peer_connection; aborting\n"); - gaim_xfer_cancel_local(xfer); - return; - } - if (!(proxy_info = peer_connection->proxy_info)) { - gaim_debug_warning("oscar","NULL proxy_info; aborting\n"); - gaim_xfer_cancel_local(xfer); - return; - } - if(peer_connection->success) { - gaim_debug_info("oscar","connection already successful, ignoring 2nd conn\n"); - return; - } - - xfer->fd = source; - peer_connection->conn->fd = source; - - proxy_info->conn = peer_connection->conn; - proxy_info->flags = AIM_RV_PROXY_CLIENT_FLAGS; - memcpy(proxy_info->cookie, peer_connection->cookie, 8); - - if(peer_connection->send_or_recv == AIM_XFER_SEND) { - if(peer_connection->stage == AIM_XFER_PROXY_STG1 || peer_connection->stage == AIM_XFER_PROXY_STG3) { - gaim_debug_info("oscar","sending INIT SEND for stage 1/3 rv proxied send\n"); - if( (err = aim_rv_proxy_init_send(proxy_info)) ) { - gaim_xfer_error(GAIM_XFER_SEND, gaim_xfer_get_account(xfer), xfer->who, - _("Unable to log into file transfer proxy.")); - gaim_debug_info("oscar", "error while sending INIT SEND rv proxy packet: %s\n", - strerror(err)); - gaim_xfer_cancel_local(xfer); - } - } else if(peer_connection->stage == AIM_XFER_PROXY_STG2) { - gaim_debug_info("oscar","sending INIT RECV for stage 2 rv proxied send\n"); - if( (err = aim_rv_proxy_init_recv(proxy_info)) ) { - gaim_xfer_error(GAIM_XFER_SEND, gaim_xfer_get_account(xfer), xfer->who, - _("Unable to log into file transfer proxy.")); - gaim_debug_info("oscar", "error while sending INIT RECV rv proxy packet: %s\n", - strerror(err)); - gaim_xfer_cancel_local(xfer); - } - } else { - gaim_debug_warning("oscar","no proxy type specified; aborting transfer\n"); - gaim_xfer_cancel_local(xfer); - } - } else if(peer_connection->send_or_recv == AIM_XFER_RECV) { - if(peer_connection->stage == AIM_XFER_PROXY_STG2) { - gaim_debug_info("oscar","sending INIT SEND for stage 2 rv proxied receive\n"); - if( (err = aim_rv_proxy_init_send(proxy_info)) ) { - gaim_xfer_error(GAIM_XFER_SEND, gaim_xfer_get_account(xfer), xfer->who, - _("Unable to log into file transfer proxy.")); - gaim_debug_info("oscar", "error while sending INIT SEND rv proxy packet: %s\n", - strerror(err)); - gaim_xfer_cancel_local(xfer); - } - } else if(peer_connection->stage == AIM_XFER_PROXY_STG1 - || peer_connection->stage == AIM_XFER_PROXY_STG3) { - gaim_debug_info("oscar","sending INIT RECV for stage 1/3 rv proxied receive\n"); - if( (err = aim_rv_proxy_init_recv(proxy_info)) ) { - gaim_xfer_error(GAIM_XFER_SEND, gaim_xfer_get_account(xfer), xfer->who, - _("Unable to log into file transfer proxy.")); - gaim_debug_info("oscar", "error while sending INIT RECV rv proxy packet: %s\n", - strerror(err)); - gaim_xfer_cancel_local(xfer); - } - } else { - gaim_debug_warning("oscar","no proxy type specified; aborting transfer\n"); - gaim_xfer_cancel_local(xfer); - } - } else { - gaim_debug_warning("oscar","no send_or_recv value specified; aborting\n"); - gaim_xfer_cancel_local(xfer); - } - free(proxy_info); - peer_connection->proxy_info = NULL; - - xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_xfer_proxylogin_cb, xfer); -} - - - /* - * xfer functions used when sending files - */ - -/* - * Send a request to another client notifying them we want to sent a file - */ -static void oscar_send_file_request(GaimXfer *xfer) -{ - PeerConnection *peer_connection = xfer->data; - GaimConnection *gc = peer_connection->sess->aux_data; - OscarData *od = gc->proto_data; - - gaim_debug_info("oscar", "AAA - in oscar_send_file_request\n"); - - if (peer_connection->conn) { - xfer->filename = g_path_get_basename(xfer->local_filename); - strncpy(peer_connection->fh.name, xfer->filename, 64); - peer_connection->fh.name[63] = '\0'; - peer_connection->fh.totsize = gaim_xfer_get_size(xfer); - peer_connection->fh.size = gaim_xfer_get_size(xfer); - - /* Calculating the checksum can take a very long time for large files */ - gaim_debug_info("oscar","calculating file checksum\n"); - peer_connection->fh.checksum = aim_oft_checksum_file(xfer->local_filename); - gaim_debug_info("oscar","checksum calculated\n"); - - memcpy(&peer_connection->fh.bcookie, peer_connection->cookie, 8); - - aim_im_sendch2_sendfile_ask(od->sess, peer_connection); - aim_conn_addhandler(od->sess, peer_connection->conn, AIM_CB_FAM_OFT, - PEER_TYPE_ESTABLISHED, oscar_sendfile_estblsh, 0); - } else { - gaim_xfer_error(GAIM_XFER_SEND, gaim_xfer_get_account(xfer), xfer->who, - _("Unable to establish listener socket or no AOL proxy connection present.")); - gaim_xfer_cancel_local(xfer); - } -} - -static void -oscar_xfer_init_listen_cb(int listenfd, gpointer data) { - GaimXfer *xfer = data; - PeerConnection *peer_connection; - GaimConnection *gc; - OscarData *od; - - /* If the ft was canceled before we get here, don't continue */ - if(gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) { - gaim_xfer_unref(xfer); - return; - } - - peer_connection = xfer->data; - gc = peer_connection->sess->aux_data; - od = gc->proto_data; - - if (listenfd < 0) { - gaim_xfer_cancel_local(xfer); - return; - } - - xfer->local_port = gaim_network_get_port_from_fd(listenfd); - peer_connection->port = xfer->local_port; - if (aim_sendfile_listen(od->sess, peer_connection, listenfd) != 0) { - gaim_xfer_cancel_local(xfer); - return; - } - gaim_debug_misc("oscar", "port is %hu, ip is %s\n", - xfer->local_port, peer_connection->clientip); - - if(peer_connection->conn) - xfer->watcher = gaim_input_add(peer_connection->conn->fd, GAIM_INPUT_READ, oscar_callback, - peer_connection->conn); - else - gaim_debug_info("oscar","NULL peer_connection->conn; not adding watcher\n"); - - oscar_send_file_request(xfer); -} - - -/* - * Opens a listener socket in preparation for sending a file - * This is not called if we are using a rendezvous proxy server - */ -static void oscar_xfer_init_send(GaimXfer *xfer) -{ - gaim_debug_info("oscar", "AAA - in oscar_xfer_init_send\n"); - - gaim_xfer_ref(xfer); - - /* Create a listening socket and an associated libfaim conn */ - if (!gaim_network_listen_range(5190, 5199, SOCK_STREAM, - oscar_xfer_init_listen_cb, xfer)) { - gaim_xfer_unref(xfer); - gaim_xfer_cancel_local(xfer); - return; - } -} - -/* - * "On second thought, you don't deserve this file." - */ -static void oscar_xfer_cancel_send(GaimXfer *xfer) -{ - PeerConnection *peer_connection = xfer->data; - GaimConnection *gc = peer_connection->sess->aux_data; - OscarData *od = gc->proto_data; - - gaim_debug_info("oscar", "AAA - in oscar_xfer_cancel_send\n"); - - if (gaim_xfer_get_status(xfer) != GAIM_XFER_STATUS_CANCEL_REMOTE) - aim_im_sendch2_sendfile_cancel(peer_connection->sess, peer_connection); - - /* Added a few sanity checks to prevent segfaulting */ - if(peer_connection) { - if(peer_connection->sess && peer_connection->conn) - oscar_connection_destroy(peer_connection->sess, peer_connection->conn); - aim_oft_destroyinfo(peer_connection); - } - xfer->data = NULL; - od->file_transfers = g_slist_remove(od->file_transfers, xfer); -} - -/* - * Called when we send some data to the other client - */ -static void oscar_xfer_ack_send(GaimXfer *xfer, const guchar *buffer, size_t size) -{ - PeerConnection *peer_connection = xfer->data; - - /* I'm not sure I like how we do this. --marv - * I do. AIM file transfers aren't really meant to be thought - * of as a transferring just a single file. The rendezvous - * establishes a connection between two computers, and then - * those computers can use the same connection for transferring - * multiple files. So we don't want the Gaim core up and closing - * the socket all willy-nilly. We want to do that in the oscar - * prpl, whenever one side or the other says they're finished - * using the connection. There might be a better way to intercept - * the socket from the core, however... --KingAnt - */ - - /* - * If we're done sending, intercept the socket from the core ft code - * and wait for the other guy to send the "done" OFT packet. - */ - if (gaim_xfer_get_bytes_remaining(xfer) <= 0) { - gaim_input_remove(xfer->watcher); - xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, peer_connection->conn); - xfer->fd = 0; - gaim_xfer_set_completed(xfer, TRUE); - } -} - -/* - * Called by the Gaim core to determine whether or not we're allowed to send a file - * to this user. - */ -static gboolean oscar_can_receive_file(GaimConnection *gc, const char *who) { - OscarData *od = gc->proto_data; - - if (od != NULL) { - aim_userinfo_t *userinfo; - userinfo = aim_locate_finduserinfo(od->sess, who); - - /* - * Don't allowing sending a file to a user that does not support - * file transfer, and don't allow sending to ourselves. - */ - if (userinfo && (userinfo->capabilities & AIM_CAPS_SENDFILE) && - aim_sncmp(who, gaim_account_get_username(gaim_connection_get_account(gc)))) - { - return TRUE; - } - - } - - return FALSE; -} - -static GaimXfer* -oscar_new_xfer(GaimConnection *gc, const char *who) { - OscarData *od; - GaimXfer *xfer; - PeerConnection *peer_connection; - const char *ip; - gboolean use_rv_proxy; - - use_rv_proxy = gaim_account_get_bool(gc->account, "use_rv_proxy", OSCAR_DEFAULT_USE_RV_PROXY); - if(use_rv_proxy) - gaim_debug_info("oscar","using stage 1 proxied transfer\n"); - - od = (OscarData *)gc->proto_data; - - /* You want to send a file to someone else, you're so generous */ - - /* Build the file transfer handle */ - xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, who); - - /* Create the oscar-specific data */ - if (use_rv_proxy) { - /* This hostname will be resolved by gaim_proxy_connect */ - xfer->remote_ip = g_strdup(AIM_RV_PROXY_SERVER_URL); - xfer->remote_port = AIM_RV_PROXY_CONNECT_PORT; - peer_connection = aim_oft_createinfo(od->sess, NULL /*cookie*/, who, 0 /*ip*/, 0, 0, 0, NULL, - AIM_XFER_SEND, AIM_XFER_PROXY, AIM_XFER_PROXY_STG1); - peer_connection->proxy_info = aim_rv_proxy_createinfo(peer_connection->sess, NULL, 0); - /* We must create a cookie before the request is sent - * so that it can be sent to the proxy */ - aim_icbm_makecookie(peer_connection->cookie); - } else { - ip = gaim_network_get_my_ip(od->conn ? od->conn->fd : -1); - peer_connection = aim_oft_createinfo(od->sess, NULL, who, ip, 0, 0, 0, NULL, - AIM_XFER_SEND, AIM_XFER_DIRECT, AIM_XFER_PROXY_NONE); - } - xfer->data = peer_connection; - - /* Setup our I/O op functions */ - if (use_rv_proxy) - gaim_xfer_set_init_fnc(xfer, oscar_xfer_init_recv); - else - gaim_xfer_set_init_fnc(xfer, oscar_xfer_init_send); - gaim_xfer_set_end_fnc(xfer, oscar_xfer_end); - gaim_xfer_set_cancel_send_fnc(xfer, oscar_xfer_cancel_send); - gaim_xfer_set_request_denied_fnc(xfer, oscar_xfer_cancel_send); - gaim_xfer_set_ack_fnc(xfer, oscar_xfer_ack_send); - - /* Keep track of this transfer for later */ - od->file_transfers = g_slist_append(od->file_transfers, xfer); - - return xfer; -} - -/* - * Called by the Gaim core when the user indicates that a file is to be sent to - * a special someone. - */ -static void oscar_send_file(GaimConnection *gc, const char *who, const char *file) { - GaimXfer *xfer = oscar_new_xfer(gc, who); - - /* Now perform the request */ - if (file) - gaim_xfer_request_accepted(xfer, file); - else - gaim_xfer_request(xfer); -} - -static int gaim_parse_auth_resp(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; + GaimConnection *gc = od->gc; GaimAccount *account = gc->account; - OscarConnection *bosconn; char *host; int port; int i, rc; + NewFlapConnectionData *new_conn_data; va_list ap; struct aim_authresp_info *info; @@ -2937,88 +1346,31 @@ gaim_debug_misc("oscar", "Reg status: %hu\n", info->regstatus); - - if (info->email) { - gaim_debug_misc("oscar", "E-mail: %s\n", info->email); - } else { - gaim_debug_misc("oscar", "E-mail is NULL\n"); - } - + gaim_debug_misc("oscar", "E-mail: %s\n", + (info->email != NULL) ? info->email : "null"); gaim_debug_misc("oscar", "BOSIP: %s\n", info->bosip); gaim_debug_info("oscar", "Closing auth connection...\n"); - oscar_connection_destroy(sess, fr->conn); - - bosconn = oscar_connection_new(sess, AIM_CONN_TYPE_BOS); - if (bosconn == NULL) { - gaim_connection_error(gc, _("Internal Error")); - od->killme = TRUE; - return 0; - } - - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); - aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_bos, 0); - aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, gaim_bosrights, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_OSERVICE, OSCAR_SUBTYPE_OSERVICE_REDIRECT, gaim_handle_redirect, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_LOCATE, OSCAR_SUBTYPE_LOCATE_RIGHTSINFO, gaim_parse_locaterights, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_BUDDY, OSCAR_SUBTYPE_BUDDY_RIGHTSINFO, gaim_parse_buddyrights, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_BUDDY, OSCAR_SUBTYPE_BUDDY_ONCOMING, gaim_parse_oncoming, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_BUDDY, OSCAR_SUBTYPE_BUDDY_OFFGOING, gaim_parse_offgoing, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICBM, OSCAR_SUBTYPE_ICBM_INCOMING, gaim_parse_incoming_im, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_LOCATE, OSCAR_SUBTYPE_LOCATE_ERROR, gaim_parse_locerr, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICBM, OSCAR_SUBTYPE_ICBM_MISSEDCALL, gaim_parse_misses, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICBM, OSCAR_SUBTYPE_ICBM_CLIENTAUTORESP, gaim_parse_clientauto, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_OSERVICE, OSCAR_SUBTYPE_OSERVICE_RATECHANGE, gaim_parse_ratechange, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_OSERVICE, OSCAR_SUBTYPE_OSERVICE_EVIL, gaim_parse_evilnotify, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_USERLOOKUP, OSCAR_SUBTYPE_USERLOOKUP_ERROR, gaim_parse_searcherror, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_USERLOOKUP, 0x0003, gaim_parse_searchreply, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICBM, OSCAR_SUBTYPE_ICBM_ERROR, gaim_parse_msgerr, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICBM, OSCAR_SUBTYPE_ICBM_MTN, gaim_parse_mtn, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_LOCATE, OSCAR_SUBTYPE_LOCATE_USERINFO, gaim_parse_userinfo, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_LOCATE, OSCAR_SUBTYPE_LOCATE_REQUESTINFOTIMEOUT, gaim_reqinfo_timeout, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_LOCATE, OSCAR_SUBTYPE_LOCATE_GOTINFOBLOCK, gaim_got_infoblock, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICBM, OSCAR_SUBTYPE_ICBM_ACK, gaim_parse_msgack, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_OSERVICE, OSCAR_SUBTYPE_OSERVICE_MOTD, gaim_parse_motd, 0); - aim_conn_addhandler(sess, bosconn, 0x0004, 0x0005, gaim_icbm_param_info, 0); - aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, gaim_memrequest, 0); - aim_conn_addhandler(sess, bosconn, 0x0001, 0x000f, gaim_selfinfo, 0); - aim_conn_addhandler(sess, bosconn, 0x0001, 0x0021, oscar_icon_req,0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICQ, OSCAR_SUBTYPE_ICQ_OFFLINEMSG, gaim_offlinemsg, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICQ, OSCAR_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE, gaim_offlinemsgdone, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_POPUP, 0x0002, gaim_popup, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICQ, OSCAR_SUBTYPE_ICQ_ALIAS, gaim_icqalias, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_ICQ, OSCAR_SUBTYPE_ICQ_INFO, gaim_icqinfo, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_ERROR, gaim_ssi_parseerr, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_RIGHTSINFO, gaim_ssi_parserights, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_LIST, gaim_ssi_parselist, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_NOLIST, gaim_ssi_parselist, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_SRVACK, gaim_ssi_parseack, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_ADD, gaim_ssi_parseadd, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_RECVAUTH, gaim_ssi_authgiven, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_RECVAUTHREQ, gaim_ssi_authrequest, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_RECVAUTHREP, gaim_ssi_authreply, 0); - aim_conn_addhandler(sess, bosconn, OSCAR_FAMILY_FEEDBAG, OSCAR_SUBTYPE_FEEDBAG_ADDED, gaim_ssi_gotadded, 0); - - od->conn = bosconn; - for (i = 0; i < (int)strlen(info->bosip); i++) { + flap_connection_schedule_destroy(conn); + + for (i = 0; i < strlen(info->bosip); i++) { if (info->bosip[i] == ':') { port = atoi(&(info->bosip[i+1])); break; } } host = g_strndup(info->bosip, i); - bosconn->status |= AIM_CONN_STATUS_INPROGRESS; - rc = gaim_proxy_connect(gc->account, host, port, oscar_bos_connect, gc); + new_conn_data = g_new(NewFlapConnectionData, 1); + new_conn_data->gc = gc; + new_conn_data->conn = flap_connection_new(od, SNAC_FAMILY_LOCATE); + new_conn_data->cookielen = info->cookielen; + new_conn_data->cookie = g_memdup(info->cookie, info->cookielen); + rc = gaim_proxy_connect(gc->account, host, port, connection_established_cb, new_conn_data); g_free(host); if (rc < 0) { gaim_connection_error(gc, _("Could Not Connect")); od->killme = TRUE; return 0; } - aim_sendcookie(sess, bosconn, info->cookielen, info->cookie); - gaim_input_remove(gc->inpa); gaim_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS); ck[3] = 0x64; @@ -3031,9 +1383,8 @@ { GaimConnection *gc = user_data; OscarData *od = gc->proto_data; - OscarSession *sess = od->sess; - - aim_auth_securid_send(sess, msg); + + aim_auth_securid_send(od, msg); } static void @@ -3049,9 +1400,9 @@ } static int -gaim_parse_auth_securid_request(OscarSession *sess, FlapFrame *fr, ...) +gaim_parse_auth_securid_request(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; + GaimConnection *gc = od->gc; GaimAccount *account = gaim_connection_get_account(gc); gchar *primary; @@ -3076,7 +1427,7 @@ unsigned long len; char *modname; int fd; - OscarConnection *conn; + FlapConnection *conn; unsigned int inpa; }; @@ -3118,7 +1469,7 @@ gaim_debug_misc(NULL, "\n"); gaim_input_remove(pos->inpa); close(pos->fd); - aim_sendmemblock(od->sess, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH); + aim_sendmemblock(od, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH); g_free(pos); } @@ -3141,9 +1492,6 @@ return; } - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - buf = g_strdup_printf("GET " AIMHASHDATA "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n", pos->offset, pos->len, pos->modname ? pos->modname : ""); write(pos->fd, buf, strlen(buf)); @@ -3157,7 +1505,7 @@ /* size of icbmui.ocm, the largest module in AIM 3.5 */ #define AIM_MAX_FILE_SIZE 98304 -int gaim_memrequest(OscarSession *sess, FlapFrame *fr, ...) { +int gaim_memrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; struct pieceofcrap *pos; guint32 offset, len; @@ -3174,7 +1522,7 @@ if (len == 0) { gaim_debug_misc("oscar", "len is 0, hashing NULL\n"); - aim_sendmemblock(sess, fr->conn, offset, len, NULL, + aim_sendmemblock(od, conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); return 1; } @@ -3201,27 +1549,28 @@ buf[i++] = (len >> 24) & 0xff; gaim_debug_misc("oscar", "len + offset is invalid, " "hashing request\n"); - aim_sendmemblock(sess, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); + aim_sendmemblock(od, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); g_free(buf); return 1; } #endif pos = g_new0(struct pieceofcrap, 1); - pos->gc = sess->aux_data; - pos->conn = fr->conn; + pos->gc = od->gc; + pos->conn = conn; pos->offset = offset; pos->len = len; pos->modname = modname ? g_strdup(modname) : NULL; - if (gaim_proxy_connect(pos->gc->account, "gaim.sourceforge.net", 80, straight_to_hell, pos) != 0) { + if (gaim_proxy_connect(pos->gc->account, "gaim.sourceforge.net", 80, straight_to_hell, pos) != 0) + { char buf[256]; if (pos->modname) g_free(pos->modname); g_free(pos); - g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. You may want to use TOC until " - "this is fixed. Check %s for updates."), GAIM_WEBSITE); + g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. " + "Check %s for updates."), GAIM_WEBSITE); gaim_notify_warning(pos->gc, NULL, _("Gaim was unable to get a valid login hash."), buf); @@ -3230,18 +1579,23 @@ return 1; } -static int gaim_parse_login(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - GaimAccount *account = gaim_connection_get_account(gc); +static int +gaim_parse_login(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) +{ + GaimConnection *gc; + GaimAccount *account; ClientInfo info = CLIENTINFO_GAIM; va_list ap; char *key; + gc = od->gc; + account = gaim_connection_get_account(gc); + va_start(ap, fr); key = va_arg(ap, char *); va_end(ap); - aim_send_login(sess, fr->conn, gaim_account_get_username(account), + aim_send_login(od, conn, gaim_account_get_username(account), gaim_connection_get_password(gc), &info, key); gaim_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS); @@ -3250,396 +1604,69 @@ return 1; } -static int conninitdone_chat(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - struct chat_connection *chatcon; - static int id = 1; - - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_CHAT, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_CHAT, OSCAR_SUBTYPE_CHAT_USERJOIN, gaim_conv_chat_join, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_CHAT, OSCAR_SUBTYPE_CHAT_USERLEAVE, gaim_conv_chat_leave, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_CHAT, OSCAR_SUBTYPE_CHAT_ROOMINFOUPDATE, gaim_conv_chat_info_update, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_CHAT, OSCAR_SUBTYPE_CHAT_INCOMINGMSG, gaim_conv_chat_incoming_msg, 0); - - aim_clientready(sess, fr->conn); - - chatcon = find_oscar_chat_by_conn(gc, fr->conn); - chatcon->id = id; - chatcon->conv = serv_got_joined_chat(gc, id++, chatcon->show); - - return 1; -} - -static int conninitdone_chatnav(OscarSession *sess, FlapFrame *fr, ...) { - - aim_conn_addhandler(sess, fr->conn, 0x000d, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_CHATNAV, OSCAR_SUBTYPE_CHATNAV_INFO, gaim_chatnav_info, 0); - - aim_clientready(sess, fr->conn); - - aim_chatnav_reqrights(sess, fr->conn); - - return 1; -} - -static int conninitdone_email(OscarSession *sess, FlapFrame *fr, ...) { - - aim_conn_addhandler(sess, fr->conn, 0x0018, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_ALERT, OSCAR_SUBTYPE_ALERT_MAILSTATUS, gaim_email_parseupdate, 0); - - aim_email_sendcookies(sess); - aim_email_activate(sess); - aim_clientready(sess, fr->conn); - - return 1; -} - -static int conninitdone_icon(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; - - aim_conn_addhandler(sess, fr->conn, 0x0018, 0x0001, gaim_parse_genericerr, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_BART, OSCAR_SUBTYPE_BART_ERROR, gaim_icon_error, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_BART, OSCAR_SUBTYPE_BART_RESPONSE, gaim_icon_parseicon, 0); - - aim_clientready(sess, fr->conn); - - od->iconconnecting = FALSE; - - if (od->icontimer) - gaim_timeout_remove(od->icontimer); - od->icontimer = gaim_timeout_add(100, gaim_icon_timerfunc, gc); - - return 1; -} - -static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition cond) { - GaimConnection *gc = data; - OscarData *od; - OscarSession *sess; - OscarConnection *tstconn; - - if (!g_list_find(gaim_connections_get_all(), gc)) { - close(source); - return; - } - - od = gc->proto_data; - sess = od->sess; - tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_CHATNAV); - tstconn->fd = source; - - if (source < 0) { - oscar_connection_destroy(sess, tstconn); - gaim_debug_error("oscar", "unable to connect to chatnav server\n"); - return; - } - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - - aim_conn_completeconnect(sess, tstconn); - od->cnpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn); - gaim_debug_info("oscar", "chatnav: connected\n"); -} - -static void oscar_auth_connect(gpointer data, gint source, GaimInputCondition cond) +static int +gaim_handle_redirect(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - GaimConnection *gc = data; - OscarData *od; - OscarSession *sess; - OscarConnection *tstconn; - - if (!g_list_find(gaim_connections_get_all(), gc)) { - close(source); - return; - } - - od = gc->proto_data; - sess = od->sess; - tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH); - tstconn->fd = source; - - if (source < 0) { - oscar_connection_destroy(sess, tstconn); - gaim_debug_error("oscar", "unable to connect to authorizer\n"); - return; - } - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - - aim_conn_completeconnect(sess, tstconn); - od->paspa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn); - gaim_debug_info("oscar", "admin: connected\n"); -} - -static void oscar_chat_connect(gpointer data, gint source, GaimInputCondition cond) -{ - struct chat_connection *ccon = data; - GaimConnection *gc = ccon->gc; - OscarData *od; - OscarSession *sess; - OscarConnection *tstconn; - - if (!g_list_find(gaim_connections_get_all(), gc)) { - close(source); - g_free(ccon->show); - g_free(ccon->name); - g_free(ccon); - return; - } - - od = gc->proto_data; - sess = od->sess; - tstconn = ccon->conn; - tstconn->fd = source; - - if (source < 0) { - oscar_connection_destroy(sess, tstconn); - g_free(ccon->show); - g_free(ccon->name); - g_free(ccon); - return; - } - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - - aim_conn_completeconnect(sess, ccon->conn); - ccon->inpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn); - od->oscar_chats = g_slist_append(od->oscar_chats, ccon); -} - -static void oscar_email_connect(gpointer data, gint source, GaimInputCondition cond) { - GaimConnection *gc = data; - OscarData *od; - OscarSession *sess; - OscarConnection *tstconn; - - if (!g_list_find(gaim_connections_get_all(), gc)) { - close(source); - return; - } - - od = gc->proto_data; - sess = od->sess; - tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_EMAIL); - tstconn->fd = source; - - if (source < 0) { - oscar_connection_destroy(sess, tstconn); - gaim_debug_error("oscar", "unable to connect to email server\n"); - return; - } - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - - aim_conn_completeconnect(sess, tstconn); - od->emlpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn); - gaim_debug_info("oscar", "email: connected\n"); -} - -static void oscar_icon_connect(gpointer data, gint source, GaimInputCondition cond) { - GaimConnection *gc = data; - OscarData *od; - OscarSession *sess; - OscarConnection *tstconn; - - if (!g_list_find(gaim_connections_get_all(), gc)) { - close(source); - return; - } - - od = gc->proto_data; - sess = od->sess; - tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_ICON); - tstconn->fd = source; - - if (source < 0) { - oscar_connection_destroy(sess, tstconn); - gaim_debug_error("oscar", "unable to connect to icon server\n"); - return; - } - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - - aim_conn_completeconnect(sess, tstconn); - od->icopa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn); - gaim_debug_info("oscar", "icon: connected\n"); -} - -/* Hrmph. I don't know how to make this look better. --mid */ -static int gaim_handle_redirect(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; + GaimConnection *gc = od->gc; GaimAccount *account = gaim_connection_get_account(gc); - OscarConnection *tstconn; - int i; - char *host; + char *host, *separator; int port; + NewFlapConnectionData *new_conn_data; va_list ap; struct aim_redirect_data *redir; - port = gaim_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT); - va_start(ap, fr); redir = va_arg(ap, struct aim_redirect_data *); va_end(ap); - for (i = 0; i < (int)strlen(redir->ip); i++) { - if (redir->ip[i] == ':') { - port = atoi(&(redir->ip[i+1])); - break; - } - } - host = g_strndup(redir->ip, i); - - switch(redir->group) { - case 0x7: /* Authorizer */ - gaim_debug_info("oscar", "Reconnecting with authorizor...\n"); - tstconn = oscar_connection_new(sess, AIM_CONN_TYPE_AUTH); - if (tstconn == NULL) { - gaim_debug_error("oscar", - "unable to reconnect with authorizer\n"); - g_free(host); - return 1; - } - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin, 0); - - tstconn->status |= AIM_CONN_STATUS_INPROGRESS; - if (gaim_proxy_connect(account, host, port, oscar_auth_connect, gc) != 0) { - oscar_connection_destroy(sess, tstconn); - gaim_debug_error("oscar", - "unable to reconnect with authorizer\n"); - g_free(host); - return 1; - } - aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie); - break; - - case 0xd: /* ChatNav */ - tstconn = oscar_connection_new(sess, AIM_CONN_TYPE_CHATNAV); - if (tstconn == NULL) { - gaim_debug_error("oscar", - "unable to connect to chatnav server\n"); - g_free(host); - return 1; - } - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chatnav, 0); - - tstconn->status |= AIM_CONN_STATUS_INPROGRESS; - if (gaim_proxy_connect(account, host, port, oscar_chatnav_connect, gc) != 0) { - oscar_connection_destroy(sess, tstconn); - gaim_debug_error("oscar", - "unable to connect to chatnav server\n"); - g_free(host); - return 1; - } - aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie); - break; - - case 0xe: { /* Chat */ - struct chat_connection *ccon; - - tstconn = oscar_connection_new(sess, AIM_CONN_TYPE_CHAT); - if (tstconn == NULL) { - gaim_debug_error("oscar", - "unable to connect to chat server\n"); - g_free(host); - return 1; - } - - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0); - - ccon = g_new0(struct chat_connection, 1); - ccon->conn = tstconn; - ccon->gc = gc; - ccon->name = g_strdup(redir->chat.room); - ccon->exchange = redir->chat.exchange; - ccon->instance = redir->chat.instance; - ccon->show = extract_name(redir->chat.room); - - ccon->conn->status |= AIM_CONN_STATUS_INPROGRESS; - if (gaim_proxy_connect(account, host, port, oscar_chat_connect, ccon) != 0) { - oscar_connection_destroy(sess, tstconn); - gaim_debug_error("oscar", - "unable to connect to chat server\n"); - g_free(host); - g_free(ccon->show); - g_free(ccon->name); - g_free(ccon); - return 1; - } - aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie); - gaim_debug_info("oscar", - "Connected to chat room %s exchange %hu\n", - ccon->name, ccon->exchange); - } break; - - case 0x0010: { /* icon */ - if (!(tstconn = oscar_connection_new(sess, AIM_CONN_TYPE_ICON))) { - gaim_debug_error("oscar", - "unable to connect to icon server\n"); - g_free(host); - return 1; - } - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_icon, 0); - - tstconn->status |= AIM_CONN_STATUS_INPROGRESS; - if (gaim_proxy_connect(account, host, port, oscar_icon_connect, gc) != 0) { - oscar_connection_destroy(sess, tstconn); - gaim_debug_error("oscar", - "unable to connect to icon server\n"); - g_free(host); - return 1; - } - aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie); - } break; - - case 0x0018: { /* email */ - if (!(tstconn = oscar_connection_new(sess, AIM_CONN_TYPE_EMAIL))) { - gaim_debug_error("oscar", - "unable to connect to email server\n"); - g_free(host); - return 1; - } - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_email, 0); - - tstconn->status |= AIM_CONN_STATUS_INPROGRESS; - if (gaim_proxy_connect(account, host, port, oscar_email_connect, gc) != 0) { - oscar_connection_destroy(sess, tstconn); - gaim_debug_error("oscar", - "unable to connect to email server\n"); - g_free(host); - return 1; - } - aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie); - } break; - - default: /* huh? */ - gaim_debug_warning("oscar", - "got redirect for unknown service 0x%04hx\n", - redir->group); - break; - } - + port = gaim_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT); + separator = strchr(redir->ip, ':'); + if (separator != NULL) + { + host = g_strndup(redir->ip, (int)separator - (int)host); + port = atoi(separator + 1); + } + else + host = g_strdup(redir->ip); + + gaim_debug_info("oscar", "Connecting to FLAP server %s:%d of type 0x%04hx\n", + host, port, redir->group); + new_conn_data = g_new(NewFlapConnectionData, 1); + new_conn_data->gc = gc; + new_conn_data->conn = flap_connection_new(od, redir->group); + new_conn_data->cookielen = redir->cookielen; + new_conn_data->cookie = g_memdup(redir->cookie, redir->cookielen); + if (new_conn_data->conn->type == SNAC_FAMILY_CHAT) + { + struct chat_connection *cc; + cc = g_new0(struct chat_connection, 1); + cc->conn = new_conn_data->conn; + cc->gc = gc; + cc->name = g_strdup(redir->chat.room); + cc->exchange = redir->chat.exchange; + cc->instance = redir->chat.instance; + cc->show = extract_name(redir->chat.room); + new_conn_data->data = cc; + gaim_debug_info("oscar", "Connecting to chat room %s exchange %hu\n", cc->name, cc->exchange); + } + + if (gaim_proxy_connect(account, host, port, connection_established_cb, new_conn_data) != 0) + { + flap_connection_schedule_destroy(new_conn_data->conn); + gaim_debug_error("oscar", "Unable to connect to FLAP server " + "of type 0x%04hx\n", redir->group); + destroy_new_conn_data(new_conn_data); + } g_free(host); + return 1; } -static int gaim_parse_oncoming(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { GaimConnection *gc; GaimAccount *account; GaimPresence *presence; - OscarData *od; struct buddyinfo *bi; time_t time_idle = 0, signon = 0; int type = 0; @@ -3650,10 +1677,9 @@ va_list ap; aim_userinfo_t *info; - gc = sess->aux_data; + gc = od->gc; account = gaim_connection_get_account(gc); presence = gaim_account_get_presence(account); - od = gc->proto_data; va_start(ap, fr); info = va_arg(ap, aim_userinfo_t *); @@ -3797,14 +1823,13 @@ static void gaim_check_comment(OscarData *od, const char *str) { if ((str == NULL) || strcmp(str, (const char *)ck)) - aim_locate_setcaps(od->sess, caps_aim); + aim_locate_setcaps(od, caps_aim); else - aim_locate_setcaps(od->sess, caps_aim | AIM_CAPS_SECUREIM); -} - -static int gaim_parse_offgoing(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; + aim_locate_setcaps(od, caps_aim | OSCAR_CAPABILITY_SECUREIM); +} + +static int gaim_parse_offgoing(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; GaimAccount *account = gaim_connection_get_account(gc); va_list ap; aim_userinfo_t *info; @@ -3820,250 +1845,8 @@ return 1; } -/* BBB */ -/* - * This is called after a remote AIM user has connected to us. - * If not using a rendezvous proxy, then we want to do some - * voodoo with the socket file descriptors. Then we always - * add a callback or two, and then send the PEER_TYPE_PROMPT. - */ -static int oscar_sendfile_estblsh(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; - GaimXfer *xfer; - PeerConnection *peer_connection; - va_list ap; - OscarConnection *conn, *listenerconn; - - gaim_debug_info("oscar", "AAA - in oscar_sendfile_estblsh\n"); - - va_start(ap, fr); - conn = va_arg(ap, OscarConnection *); - listenerconn = va_arg(ap, OscarConnection *); - va_end(ap); - - /* Finding by conn will work for proxied connections only - * Finding by listenerconn will work for direct connections only */ - if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, conn))) { - if(!(xfer = oscar_find_xfer_by_conn(od->file_transfers, listenerconn))) { - gaim_debug_warning("oscar","xfer not found via connection\n"); - return 1; - } - } - if (!(peer_connection = xfer->data)) { - gaim_debug_warning("oscar","NULL data\n"); - return 1; - } - - /* Mark connection as success so further connections aren't attempted - * This is important here since some receive file code paths pass through here */ - peer_connection->success = TRUE; - - if(peer_connection->method != AIM_XFER_PROXY) { - /* Stop watching listener conn; watch transfer conn instead */ - gaim_input_remove(xfer->watcher); - - oscar_connection_destroy(sess, listenerconn); - - peer_connection->conn = conn; - xfer->fd = peer_connection->conn->fd; - } - - xfer->watcher = gaim_input_add(peer_connection->conn->fd, GAIM_INPUT_READ, oscar_callback, peer_connection->conn); - - if(peer_connection->send_or_recv == AIM_XFER_SEND) { - aim_conn_addhandler(peer_connection->sess, peer_connection->conn, AIM_CB_FAM_OFT, PEER_TYPE_ACK, - oscar_sendfile_ack, 0); - aim_conn_addhandler(peer_connection->sess, peer_connection->conn, AIM_CB_FAM_OFT, PEER_TYPE_DONE, - oscar_sendfile_done, 0); - - /* Inform the other user that we are connected and ready to transfer */ - aim_oft_sendheader(sess, PEER_TYPE_PROMPT, peer_connection); - } - - /* For a file send, we'll hopefully end up in oscar_sendfile_ack next - * For a file receive, oscar_sendfile_prompt */ - - return 0; -} - -/* - * This is the gaim callback passed to gaim_proxy_connect when - * connecting to another AIM user in order to transfer a file - * Takes xfer as data and fd as source - * BBB - */ -static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition) { - GaimXfer *xfer; - PeerConnection *peer_connection; - - gaim_debug_info("oscar", "AAA - in oscar_sendfile_connected\n"); - if (!(xfer = data)) - return; - if (!(peer_connection = xfer->data)) - return; - if(peer_connection->success) { - gaim_debug_info("oscar","connection already successful; ignoring 2nd conn\n"); - return; - } - - if (source < 0) { - gaim_debug_info("oscar","received fd of %d; aborting transfer\n", source); - gaim_xfer_cancel_remote(xfer); - return; - } - peer_connection->success = TRUE; /* Mark this connection as successful before it times out */ - - /* XXX:NBIO remove when nonblocking I/O implemented for oscar */ - fcntl(source, F_SETFL, 0); - - /* We might have already set these in oscar_sendfile_proxylogin, but it won't - * hurt to do it again since it is rather necessary */ - xfer->fd = source; - peer_connection->conn->fd = source; - - aim_conn_completeconnect(peer_connection->sess, peer_connection->conn); - - xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, peer_connection->conn); - - /* Inform the other user that we are connected and accept the transfer - * Except for a stage 2 receive, then we'll be the ones receiving this accept message */ - if(peer_connection->stage != AIM_XFER_PROXY_STG2) - aim_im_sendch2_sendfile_accept(peer_connection->sess, peer_connection); - - /* Don't wait around if this is a redirected send */ - if(peer_connection->send_or_recv == AIM_XFER_SEND) { - /* We should only get here if this is a redirected file send */ - aim_conn_addhandler(peer_connection->sess, peer_connection->conn, AIM_CB_FAM_OFT, PEER_TYPE_ACK, - oscar_sendfile_ack, 0); - aim_conn_addhandler(peer_connection->sess, peer_connection->conn, AIM_CB_FAM_OFT, PEER_TYPE_DONE, - oscar_sendfile_done, 0); - - /* Inform the other user that we are ready to transfer */ - aim_oft_sendheader(peer_connection->sess, PEER_TYPE_PROMPT, peer_connection); - } -} - -/* - * This is called when a buddy sends us some file info. This happens when they - * are sending a file to you, and you have just established a connection to them. - * You should send them the exact same info except use the real cookie. We also - * get like totally ready to like, receive the file, kay? - */ -static int oscar_sendfile_prompt(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; - GaimXfer *xfer; - PeerConnection *peer_connection; - va_list ap; - OscarConnection *conn; - guint8 *cookie; - PeerFrame *fh; - - gaim_debug_info("oscar", "AAA - in oscar_sendfile_prompt\n"); - - va_start(ap, fr); - conn = va_arg(ap, OscarConnection *); - cookie = va_arg(ap, guint8 *); - fh = va_arg(ap, PeerFrame *); - va_end(ap); - - if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, conn))) - return 1; - - if (!(peer_connection = xfer->data)) - return 1; - - /* We want to stop listening with a normal thingy */ - gaim_input_remove(xfer->watcher); - xfer->watcher = 0; - - /* They sent us some information about the file they're sending */ - memcpy(&peer_connection->fh, fh, sizeof(*fh)); - - /* Fill in the cookie */ - memcpy(&peer_connection->fh.bcookie, peer_connection->cookie, 8); - - /* XXX - convert the name from UTF-8 to UCS-2 if necessary, and pass the encoding to the call below */ - aim_oft_sendheader(peer_connection->sess, PEER_TYPE_ACK, peer_connection); - gaim_xfer_start(xfer, xfer->fd, NULL, 0); - - return 0; -} - -/* - * We are sending a file to someone else. They have just acknowledged our - * prompt, so we want to start sending data like there's no tomorrow. - */ -static int oscar_sendfile_ack(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; - GaimXfer *xfer; - va_list ap; - OscarConnection *conn; - guint8 *cookie; - PeerFrame *fh; - - gaim_debug_info("oscar", "AAA - in oscar_sendfile_ack\n"); - va_start(ap, fr); - conn = va_arg(ap, OscarConnection *); - cookie = va_arg(ap, guint8 *); - fh = va_arg(ap, PeerFrame *); - va_end(ap); - - if (!(xfer = oscar_find_xfer_by_cookie(od->file_transfers, cookie))) - return 1; - - /* We want to stop listening with a normal thingy */ - gaim_input_remove(xfer->watcher); - xfer->watcher = 0; - - gaim_xfer_start(xfer, xfer->fd, NULL, 0); - - return 0; -} - -/* - * We just sent a file to someone. They said they got it and everything, - * so we can close our direct connection and what not. - */ -static int oscar_sendfile_done(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; - GaimXfer *xfer; - va_list ap; - OscarConnection *conn; - guint8 *cookie; - PeerFrame *fh; - PeerConnection *peer_connection; - - gaim_debug_info("oscar", "AAA - in oscar_sendfile_done\n"); - va_start(ap, fr); - conn = va_arg(ap, OscarConnection *); - cookie = va_arg(ap, guint8 *); - fh = va_arg(ap, PeerFrame *); - va_end(ap); - - if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, conn))) { - gaim_debug_warning("oscar","xfer not found\n"); - return 1; - } - if(!(peer_connection = xfer->data)) { - gaim_debug_warning("oscar","NULL peer_connection\n"); - return 1; - } - if(fh->nrecvd == fh->size) - gaim_xfer_set_completed(xfer, TRUE); - - xfer->fd = conn->fd; - gaim_xfer_end(xfer); - - return 0; -} - -static int incomingim_chan1(OscarSession *sess, OscarConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; +static int incomingim_chan1(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) { + GaimConnection *gc = od->gc; GaimAccount *account = gaim_connection_get_account(gc); GaimMessageFlags flags = 0; struct buddyinfo *bi; @@ -4121,7 +1904,7 @@ "Sending buddy icon to %s (%d bytes, " "%lu reported)\n", userinfo->sn, len, st.st_size); - aim_im_sendch2_icon(sess, userinfo->sn, buf, st.st_size, + aim_im_sendch2_icon(od, userinfo->sn, buf, st.st_size, st.st_mtime, aimutil_iconsum(buf, st.st_size)); fclose(file); } else @@ -4199,17 +1982,18 @@ return 1; } -static int incomingim_chan2(OscarSession *sess, OscarConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args) { +static int +incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, IcbmArgsCh2 *args) +{ GaimConnection *gc; GaimAccount *account; - OscarData *od; const char *username = NULL; char *message = NULL; - g_return_val_if_fail(sess != NULL, 0); - g_return_val_if_fail(sess->aux_data != NULL, 0); - - gc = sess->aux_data; + g_return_val_if_fail(od != NULL, 0); + g_return_val_if_fail(od->gc != NULL, 0); + + gc = od->gc; account = gaim_connection_get_account(gc); od = gc->proto_data; username = gaim_account_get_username(account); @@ -4217,8 +2001,8 @@ if (args == NULL) return 0; - gaim_debug_misc("oscar", "rendezvous with %s, status is %hu\n", - userinfo->sn, args->status); + gaim_debug_misc("oscar", "Incoming rendezvous message of type %u, " + "user %s, status %hu\n", args->type, userinfo->sn, args->status); if (args->msg != NULL) { @@ -4234,7 +2018,8 @@ } } - if (args->reqclass & AIM_CAPS_CHAT) { + if (args->type & OSCAR_CAPABILITY_CHAT) + { char *name; GHashTable *components; @@ -4245,8 +2030,10 @@ components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); name = extract_name(args->info.chat.roominfo.name); - g_hash_table_replace(components, g_strdup("room"), g_strdup(name ? name : args->info.chat.roominfo.name)); - g_hash_table_replace(components, g_strdup("exchange"), g_strdup_printf("%d", args->info.chat.roominfo.exchange)); + g_hash_table_replace(components, g_strdup("room"), + g_strdup(name ? name : args->info.chat.roominfo.name)); + g_hash_table_replace(components, g_strdup("exchange"), + g_strdup_printf("%d", args->info.chat.roominfo.exchange)); serv_got_chat_invite(gc, name ? name : args->info.chat.roominfo.name, userinfo->sn, @@ -4254,322 +2041,83 @@ components); if (name) g_free(name); - } else if (args->reqclass & AIM_CAPS_SENDFILE) { -/* BBB */ - /* This is the first sendfile request where we need to notify the user that someone - * wants to send a file */ - if (args->status == AIM_RENDEZVOUS_PROPOSE - && (args->info.sendfile.reqnum == 0x0001)) { - /* Someone wants to send a file (or files) to us */ - GaimXfer *xfer; - PeerConnection *peer_connection; - PeerProxyInfo *proxy_info = NULL; - gboolean use_rv_proxy; - int proxy_stage; - int xfer_method; - const char *proxy_ip = NULL; - - if (!args->cookie || !args->port || - !args->info.sendfile.filename || !args->info.sendfile.totsize || - !args->info.sendfile.totfiles || !args->reqclass) { - gaim_debug_warning("oscar", - "%s tried to send you a file with incomplete " - "information.\n", userinfo->sn); - g_free(message); - return 1; - } - - if (args->info.sendfile.subtype == AIM_OFT_SUBTYPE_SEND_DIR) { - /* last char of the ft req is a star, they are sending us a - * directory -- remove the star and trailing slash so we don't save - * directories that look like 'dirname\*' -- arl */ - char *tmp = strrchr(args->info.sendfile.filename, '\\'); - if (tmp && (tmp[1] == '*')) { - tmp[0] = '\0'; - } - gaim_debug_warning("oscar", - "We're receiving a whole directory! What fun! " - "Especially since we don't support that!\n"); - } - - /* Build the file transfer handle */ - xfer = gaim_xfer_new(gc->account, GAIM_XFER_RECEIVE, userinfo->sn); - - use_rv_proxy = gaim_account_get_bool(account, "use_rv_proxy", OSCAR_DEFAULT_USE_RV_PROXY); - - if(args->info.sendfile.use_proxy) { - /* The sender requested (stage 1) that we use a rendezvous proxy */ - xfer_method = AIM_XFER_PROXY; - proxy_stage = AIM_XFER_PROXY_STG1; - gaim_debug_info("oscar","using stage 1 proxy with ip: %s\n", - args->proxyip, args->port); - xfer->remote_ip = g_strdup(args->proxyip); - xfer->remote_port = AIM_RV_PROXY_CONNECT_PORT; - proxy_info = aim_rv_proxy_createinfo(od->sess, args->cookie, args->port); - } else if(use_rv_proxy) { - /* If the local user indicated that a rendezvous proxy is necessary - * start a stage 2 proxied transfer */ - gaim_debug_info("oscar","using stage 2 proxied transfer\n"); - xfer_method = AIM_XFER_PROXY; - proxy_stage = AIM_XFER_PROXY_STG2; - /* This hostname will be resolved by gaim_proxy_connect */ - xfer->remote_ip = g_strdup(AIM_RV_PROXY_SERVER_URL); - xfer->remote_port = AIM_RV_PROXY_CONNECT_PORT; - proxy_info = aim_rv_proxy_createinfo(od->sess, args->cookie, 0); - } else { - /* We are receiving a file directly with no rendezvous proxy */ - xfer_method = AIM_XFER_DIRECT; - proxy_stage = AIM_XFER_PROXY_NONE; - xfer->remote_ip = g_strdup(args->clientip); - xfer->remote_port = args->port; - } - - /* Use UTF8 so that the world will be a happier place */ - if (g_utf8_validate(args->info.sendfile.filename, -1, - NULL)) { - gaim_xfer_set_filename(xfer, - args->info.sendfile.filename); - } else { - gchar * utf8_filename = gaim_utf8_salvage( - args->info.sendfile.filename); - gaim_xfer_set_filename(xfer, utf8_filename); - g_free(utf8_filename); - } - - gaim_xfer_set_size(xfer, args->info.sendfile.totsize); - - /* Ignore messages that start with <ICQ_COOL_FT> (XML that is sent along - * with ICQ sendfile requests) & <HTML> message that is sent with AOL file - * transfers (Note: this latter message is ignored only if whole message - * is <HTML>, but not if it starts with <HTML> */ - if(message && ( g_ascii_strncasecmp(message,"<ICQ_COOL_FT>",13) < 0 - || g_ascii_strcasecmp(message,"<HTML>") == 0) ) { - gaim_debug_info("oscar","Ignoring file transfer message: %s\n", message); - g_free(message); - message = NULL; - } - gaim_xfer_set_message(xfer, message); - - /* Create the oscar-specific data */ - peer_connection = aim_oft_createinfo(od->sess, args->cookie, userinfo->sn, args->clientip, - xfer->remote_port, 0, 0, NULL, AIM_XFER_RECV, xfer_method, proxy_stage); - if(proxy_stage == AIM_XFER_PROXY_STG2 && proxy_ip) { - peer_connection->proxyip = g_strdup(proxy_ip); - } else { - if (args->proxyip) - peer_connection->proxyip = g_strdup(args->proxyip); - if (args->verifiedip) - peer_connection->verifiedip = g_strdup(args->verifiedip); + } + + else if ((args->type & OSCAR_CAPABILITY_SENDFILE) || + (args->type & OSCAR_CAPABILITY_DIRECTIM)) + { + if (args->status == AIM_RENDEZVOUS_PROPOSE) + { + peer_connection_got_proposition(od, userinfo->sn, message, args); + } + else if (args->status == AIM_RENDEZVOUS_CANCEL) + { + /* The other user canceled a peer request */ + PeerConnection *conn; + + conn = peer_connection_find_by_cookie(od, userinfo->sn, args->cookie); + /* + * If conn is NULL it means we haven't tried to create + * a connection with that user. They may be trying to + * do something malicious. + */ + if (conn != NULL) + { + peer_connection_destroy(conn, PEER_DISCONNECT_REMOTE_CLOSED); } - peer_connection->proxy_info = proxy_info; - xfer->data = peer_connection; - - /* Setup our I/O op functions */ - gaim_xfer_set_init_fnc(xfer, oscar_xfer_init_recv); - gaim_xfer_set_end_fnc(xfer, oscar_xfer_end); - gaim_xfer_set_request_denied_fnc(xfer, oscar_xfer_cancel_recv); - gaim_xfer_set_cancel_recv_fnc(xfer, oscar_xfer_cancel_recv); - gaim_xfer_set_ack_fnc(xfer, oscar_xfer_ack_recv); - - /* Keep track of this transfer for later */ - od->file_transfers = g_slist_append(od->file_transfers, xfer); - - /* Now perform the request */ - gaim_xfer_request(xfer); - /* A secondary request has been sent to negotiate the connection method */ - } else if (args->status == AIM_RENDEZVOUS_PROPOSE && args->info.sendfile.reqnum == 0x0002) { - /* We have asked to send a file to someone else, but they sent us a reply request - * asking us to use an alternative method of connecting */ - GaimXfer *xfer; - PeerConnection *peer_connection; - - if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, args->cookie))) { - peer_connection = xfer->data; - - /* Stop the listener connection */ - gaim_input_remove(xfer->watcher); - oscar_connection_destroy(sess, peer_connection->conn); /* This is currently the listener */ - - if(args->info.sendfile.use_proxy) { - gaim_debug_info("oscar", - "received request for stage 2 rv proxy with ip: %s\n", - args->proxyip); - peer_connection->method = AIM_XFER_PROXY; - peer_connection->stage = AIM_XFER_PROXY_STG2; - - peer_connection->proxy_info = aim_rv_proxy_createinfo(peer_connection->sess, - args->cookie, args->port); - if(args->proxyip) { - if(xfer->remote_ip) - g_free(xfer->remote_ip); - xfer->remote_ip = g_strdup(args->proxyip); - xfer->remote_port = AIM_RV_PROXY_CONNECT_PORT; - oscar_xfer_init_recv(xfer); - } else { - gaim_debug_warning("oscar", - "stage 2 rv proxy file send: no proxy ip specified\n"); - } - } else if(args->clientip - && g_ascii_strcasecmp(args->clientip,"0.0.0.0") == 0) + } + else if (args->status == AIM_RENDEZVOUS_CONNECTED) + { + /* Remote user has accepted our peer request */ + PeerConnection *conn; + + conn = peer_connection_find_by_cookie(od, userinfo->sn, args->cookie); + /* + * If conn is NULL it means we haven't tried to create + * a connection with that user. They may be trying to + * do something malicious. + */ + if (conn != NULL) + { + if (conn->listenerfd != -1) { - gaim_debug_warning("oscar", - "other client wants us to send stage 3 proxy info\n"); - peer_connection->method = AIM_XFER_PROXY; - peer_connection->stage = AIM_XFER_PROXY_STG3; - - /* Clean useless data from peer_connection */ - peer_connection->clientip = NULL; - peer_connection->verifiedip = NULL; - - /* This hostname will be resolved in gaim_proxy_connect */ - xfer->remote_ip = g_strdup(AIM_RV_PROXY_SERVER_URL); - xfer->remote_port = AIM_RV_PROXY_CONNECT_PORT; - - peer_connection->proxy_info - = aim_rv_proxy_createinfo(od->sess, args->cookie, 0); - oscar_xfer_init_recv(xfer); - } else { - gaim_debug_info("oscar","received request to redirect transfer; clientip/verifiedip: %s / %s\n", - args->clientip, args->verifiedip); - peer_connection->method = AIM_XFER_REDIR; - if (args->verifiedip) - peer_connection->verifiedip = g_strdup(args->verifiedip); - if (args->clientip) { - peer_connection->clientip = g_strdup(args->clientip); - xfer->remote_ip = g_strdup(args->clientip); - } - xfer->remote_port = args->port; - - /* This file send will briefly follow file receive codepaths */ - oscar_xfer_init_recv(xfer); + /* + * If they are connecting directly to us then + * continue the peer negotiation by + * accepting connections on our listener port. + */ + conn->watcher_incoming = gaim_input_add(conn->listenerfd, + GAIM_INPUT_READ, peer_connection_listen_cb, conn); } - } else { - gaim_debug_warning("oscar","received file tranfer reply request: xfer not found\n"); } - /* A THIRD request has been sent trying to figure out what connection method will be used - * to transfer this file */ - } else if (args->status == AIM_RENDEZVOUS_PROPOSE && args->info.sendfile.reqnum == 0x0003) { - /* We are receiving a file from someone. We sent a request to use a stage 3 - * proxy. They did the initial proxy login and have sent us the info in a - * third file transfer request. */ - GaimXfer *xfer; - PeerConnection *peer_connection; - - if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, args->cookie))) { - peer_connection = xfer->data; - - /* We are receiving a file */ - gaim_debug_info("oscar", - "other client sent us stage 3 proxy info\n"); - - /* The following pieces of information should already have - * been set in oscar_xfer_ip_timeout, but we'll list them - * again just for clarity. */ - peer_connection->method = AIM_XFER_PROXY; - peer_connection->stage = AIM_XFER_PROXY_STG3; - - peer_connection->proxy_info = aim_rv_proxy_createinfo(peer_connection->sess, - args->cookie, args->port); - if(args->proxyip) { - if(xfer->remote_ip) - g_free(xfer->remote_ip); - xfer->remote_ip = g_strdup(args->proxyip); - xfer->remote_port = AIM_RV_PROXY_CONNECT_PORT; - oscar_xfer_init_recv(xfer); - } else { - gaim_debug_warning("oscar", - "stage 3 rv proxy file receive: no proxy ip specified\n"); - } - } else { - gaim_debug_warning("oscar","received file tranfer reply request: xfer not found\n"); - } - } else if (args->status == AIM_RENDEZVOUS_CANCEL) { - /* The other user wants to cancel a file transfer */ - GaimXfer *xfer; - gaim_debug_info("oscar", - "AAA - File transfer canceled by remote user\n"); - if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, args->cookie))) - gaim_xfer_cancel_remote(xfer); - } else if (args->status == AIM_RENDEZVOUS_ACCEPT) { - /* - * This gets sent by the receiver of a file - * as they connect directly to us. If we don't - * get this, then maybe a third party connected - * to us, and we shouldn't send them anything. - */ - gaim_debug_info("oscar", - "AAA - received chan 2 AIM_RENDEZVOUS_ACCEPT; ignoring\n"); - } else { - gaim_debug_error("oscar", - "unknown rendezvous status!\n"); } - } else if (args->reqclass & AIM_CAPS_GETFILE) { - } else if (args->reqclass & AIM_CAPS_TALK) { - } else if (args->reqclass & AIM_CAPS_BUDDYICON) { + } + + else if (args->type & OSCAR_CAPABILITY_GETFILE) + { + } + + else if (args->type & OSCAR_CAPABILITY_TALK) + { + } + + else if (args->type & OSCAR_CAPABILITY_BUDDYICON) + { gaim_buddy_icons_set_for_user(account, userinfo->sn, args->info.icon.icon, args->info.icon.length); - } else if (args->reqclass & AIM_CAPS_DIRECTIM) { - /* Consider moving all this into a helper func in the direct im block way up there */ - struct ask_direct *d = g_new0(struct ask_direct, 1); - struct oscar_direct_im *dim = oscar_direct_im_find(od, userinfo->sn); - char buf[256]; - - if (!args->verifiedip) { - /* TODO: do something about this, after figuring out what it means */ - gaim_debug_info("oscar", - "directim kill blocked (%s)\n", userinfo->sn); - g_free(message); - return 1; - } - - gaim_debug_info("oscar", - "%s received direct im request from %s (%s)\n", - username, userinfo->sn, args->verifiedip); - - d->gc = gc; - d->sn = g_strdup(userinfo->sn); - /* Let's use the clientip here, because I think that's what AIM does. - * Besides, if the clientip is wrong, we'll probably timeout faster, - * and then ask them to connect to us. */ - /* - * I disagree, let's use the verifiedip. I think AIM tries the - * verified IP first, then tries the client IP if that fails. In - * any case, there's a better chance the verified IP will be correct. - * The client IP is what the other person _thinks_ their IP address - * is. The verified IP is the address that the AIM server sees the - * other person using. - */ - snprintf(d->ip, sizeof(d->ip), "%s:%d", args->verifiedip, args->port?args->port:5190); - memcpy(d->cookie, args->cookie, 8); - if (dim && !dim->connected && aim_odc_getcookie(dim->conn) && args->cookie && - (!memcmp(aim_odc_getcookie(dim->conn), args->cookie, 8))) { - - oscar_direct_im_destroy(od, dim); - d->donttryagain = TRUE; - accept_direct_im_request(d); - } else { - if (dim && !dim->connected) - gaim_debug_warning("oscar", "DirectIM: received direct im request " - "while already connected to that buddy!"); - g_snprintf(buf, sizeof buf, _("%s has just asked to directly connect to %s"), userinfo->sn, username); - - gaim_request_action(gc, NULL, buf, - _("This requires a direct connection between " - "the two computers and is necessary for IM " - "Images. Because your IP address will be " - "revealed, this may be considered a privacy " - "risk."), - GAIM_DEFAULT_ACTION_NONE, d, 2, - _("_Connect"), G_CALLBACK(accept_direct_im_request), - _("Cancel"), G_CALLBACK(destroy_direct_im_request)); - /* FIXME: we should actually send a packet on cancel */ - } - } else if (args->reqclass & AIM_CAPS_ICQSERVERRELAY) { - gaim_debug_error("oscar", "Got an ICQ Server Relay message of type %d\n", args->info.rtfmsg.msgtype); - } else { - gaim_debug_error("oscar", - "Unknown reqclass %hu\n", args->reqclass); + } + + else if (args->type & OSCAR_CAPABILITY_ICQSERVERRELAY) + { + gaim_debug_error("oscar", "Got an ICQ Server Relay message of " + "type %d\n", args->info.rtfmsg.msgtype); + } + + else + { + gaim_debug_error("oscar", "Unknown request class %hu\n", + args->type); } g_free(message); @@ -4583,7 +2131,9 @@ * methods of authorization (SSI and old-school channel 4 ICBM) */ /* When you ask other people for authorization */ -static void gaim_auth_request(struct name_data *data, char *msg) { +static void +gaim_auth_request(struct name_data *data, char *msg) +{ GaimConnection *gc = data->gc; if (g_list_find(gaim_connections_get_all(), gc)) { @@ -4594,14 +2144,16 @@ gaim_debug_info("oscar", "ssi: adding buddy %s to group %s\n", buddy->name, group->name); - aim_ssi_sendauthrequest(od->sess, data->name, msg ? msg : _("Please authorize me so I can add you to my buddy list.")); - if (!aim_ssi_itemlist_finditem(od->sess->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY)) - aim_ssi_addbuddy(od->sess, buddy->name, group->name, gaim_buddy_get_alias_only(buddy), NULL, NULL, 1); + aim_ssi_sendauthrequest(od, data->name, msg ? msg : _("Please authorize me so I can add you to my buddy list.")); + if (!aim_ssi_itemlist_finditem(od->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY)) + aim_ssi_addbuddy(od, buddy->name, group->name, gaim_buddy_get_alias_only(buddy), NULL, NULL, 1); } } } -static void gaim_auth_request_msgprompt(struct name_data *data) { +static void +gaim_auth_request_msgprompt(struct name_data *data) +{ gaim_request_input(data->gc, NULL, _("Authorization Request Message:"), NULL, _("Please authorize me!"), TRUE, FALSE, NULL, _("OK"), G_CALLBACK(gaim_auth_request), @@ -4609,7 +2161,9 @@ data); } -static void gaim_auth_dontrequest(struct name_data *data) { +static void +gaim_auth_dontrequest(struct name_data *data) +{ GaimConnection *gc = data->gc; if (g_list_find(gaim_connections_get_all(), gc)) { @@ -4622,7 +2176,9 @@ } -static void gaim_auth_sendrequest(GaimConnection *gc, char *name) { +static void +gaim_auth_sendrequest(GaimConnection *gc, char *name) +{ struct name_data *data = g_new0(struct name_data, 1); GaimBuddy *buddy; gchar *dialog_msg, *nombre; @@ -4649,7 +2205,9 @@ } -static void gaim_auth_sendrequest_menu(GaimBlistNode *node, gpointer ignored) { +static void +gaim_auth_sendrequest_menu(GaimBlistNode *node, gpointer ignored) +{ GaimBuddy *buddy; GaimConnection *gc; @@ -4661,28 +2219,34 @@ } /* When other people ask you for authorization */ -static void gaim_auth_grant(struct name_data *data) { +static void +gaim_auth_grant(struct name_data *data) +{ GaimConnection *gc = data->gc; if (g_list_find(gaim_connections_get_all(), gc)) { OscarData *od = gc->proto_data; - aim_ssi_sendauthreply(od->sess, data->name, 0x01, NULL); + aim_ssi_sendauthreply(od, data->name, 0x01, NULL); } oscar_free_name_data(data); } /* When other people ask you for authorization */ -static void gaim_auth_dontgrant(struct name_data *data, char *msg) { +static void +gaim_auth_dontgrant(struct name_data *data, char *msg) +{ GaimConnection *gc = data->gc; if (g_list_find(gaim_connections_get_all(), gc)) { OscarData *od = gc->proto_data; - aim_ssi_sendauthreply(od->sess, data->name, 0x00, msg ? msg : _("No reason given.")); - } -} - -static void gaim_auth_dontgrant_msgprompt(struct name_data *data) { + aim_ssi_sendauthreply(od, data->name, 0x00, msg ? msg : _("No reason given.")); + } +} + +static void +gaim_auth_dontgrant_msgprompt(struct name_data *data) +{ gaim_request_input(data->gc, NULL, _("Authorization Denied Message:"), NULL, _("No reason given."), TRUE, FALSE, NULL, _("OK"), G_CALLBACK(gaim_auth_dontgrant), @@ -4691,7 +2255,9 @@ } /* When someone sends you buddies */ -static void gaim_icq_buddyadd(struct name_data *data) { +static void +gaim_icq_buddyadd(struct name_data *data) +{ GaimConnection *gc = data->gc; if (g_list_find(gaim_connections_get_all(), gc)) { @@ -4701,8 +2267,10 @@ oscar_free_name_data(data); } -static int incomingim_chan4(OscarSession *sess, OscarConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args, time_t t) { - GaimConnection *gc = sess->aux_data; +static int +incomingim_chan4(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args, time_t t) +{ + GaimConnection *gc = od->gc; GaimAccount *account = gaim_connection_get_account(gc); gchar **msg1, **msg2; int i, numtoks; @@ -4711,7 +2279,7 @@ return 1; gaim_debug_info("oscar", - "Received a channel 4 message of type 0x%02hhx.\n", + "Received a channel 4 message of type 0x%02hx.\n", args->type); /* @@ -4899,7 +2467,7 @@ return 1; } -static int gaim_parse_incoming_im(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_parse_incoming_im(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { guint16 channel; int ret = 0; aim_userinfo_t *userinfo; @@ -4913,19 +2481,19 @@ case 1: { /* standard message */ struct aim_incomingim_ch1_args *args; args = va_arg(ap, struct aim_incomingim_ch1_args *); - ret = incomingim_chan1(sess, fr->conn, userinfo, args); + ret = incomingim_chan1(od, conn, userinfo, args); } break; case 2: { /* rendezvous */ - struct aim_incomingim_ch2_args *args; - args = va_arg(ap, struct aim_incomingim_ch2_args *); - ret = incomingim_chan2(sess, fr->conn, userinfo, args); + IcbmArgsCh2 *args; + args = va_arg(ap, IcbmArgsCh2 *); + ret = incomingim_chan2(od, conn, userinfo, args); } break; case 4: { /* ICQ */ struct aim_incomingim_ch4_args *args; args = va_arg(ap, struct aim_incomingim_ch4_args *); - ret = incomingim_chan4(sess, fr->conn, userinfo, args, 0); + ret = incomingim_chan4(od, conn, userinfo, args, 0); } break; default: { @@ -4940,8 +2508,8 @@ return ret; } -static int gaim_parse_misses(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_parse_misses(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; GaimAccount *account = gaim_connection_get_account(gc); char *buf; va_list ap; @@ -5013,46 +2581,43 @@ } if (!gaim_conv_present_error(userinfo->sn, account, buf)) - gaim_notify_error(sess->aux_data, NULL, buf, NULL); + gaim_notify_error(od->gc, NULL, buf, NULL); g_free(buf); return 1; } -static int gaim_parse_clientauto_ch2(OscarSession *sess, const char *who, guint16 reason, const guchar *cookie) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; - -/* BBB */ - switch (reason) { - case 3: { /* Decline sendfile. */ - GaimXfer *xfer; - struct oscar_direct_im *dim; - - gaim_debug_info("oscar", - "AAA - Other user declined some sort of direct " - "connect attempt (automaticly?)\n"); - if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, cookie))) - gaim_xfer_cancel_remote(xfer); - else if ((dim = oscar_direct_im_find(od, who))) { - /* AAA should use find by cookie or something here */ - oscar_direct_im_disconnect(od, dim); - } - } break; - - default: { - gaim_debug_warning("oscar", - "Received an unknown rendezvous client auto-response " - "from %s. Type 0x%04hx\n", who, reason); +static int +gaim_parse_clientauto_ch2(OscarData *od, const char *who, guint16 reason, const guchar *cookie) +{ + if (reason == 0x0003) + { + /* Rendezvous was refused. */ + PeerConnection *conn; + + conn = peer_connection_find_by_cookie(od, who, cookie); + + if (conn == NULL) + { + gaim_debug_info("oscar", "Received a rendezvous cancel message " + "for a nonexistant connection from %s.\n", who); } - + else + { + peer_connection_destroy(conn, PEER_DISCONNECT_REMOTE_REFUSED); + } + } + else + { + gaim_debug_warning("oscar", "Received an unknown rendezvous " + "message from %s. Type 0x%04hx\n", who, reason); } return 0; } -static int gaim_parse_clientauto_ch4(OscarSession *sess, char *who, guint16 reason, guint32 state, char *msg) { - GaimConnection *gc = sess->aux_data; +static int gaim_parse_clientauto_ch4(OscarData *od, char *who, guint16 reason, guint32 state, char *msg) { + GaimConnection *gc = od->gc; switch(reason) { case 0x0003: { /* Reply from an ICQ status message request */ @@ -5083,7 +2648,7 @@ return 0; } -static int gaim_parse_clientauto(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_parse_clientauto(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; guint16 chan, reason; char *who; @@ -5095,7 +2660,7 @@ if (chan == 0x0002) { /* File transfer declined */ guchar *cookie = va_arg(ap, guchar *); - return gaim_parse_clientauto_ch2(sess, who, reason, cookie); + return gaim_parse_clientauto_ch2(od, who, reason, cookie); } else if (chan == 0x0004) { /* ICQ message */ guint32 state = 0; char *msg = NULL; @@ -5103,7 +2668,7 @@ state = va_arg(ap, guint32); msg = va_arg(ap, char *); } - return gaim_parse_clientauto_ch4(sess, who, reason, state, msg); + return gaim_parse_clientauto_ch4(od, who, reason, state, msg); } va_end(ap); @@ -5111,7 +2676,7 @@ return 1; } -static int gaim_parse_genericerr(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_parse_genericerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; guint16 reason; char *m; @@ -5126,15 +2691,15 @@ m = g_strdup_printf(_("SNAC threw error: %s\n"), reason < msgerrreasonlen ? _(msgerrreason[reason]) : _("Unknown error")); - gaim_notify_error(sess->aux_data, NULL, m, NULL); + gaim_notify_error(od->gc, NULL, m, NULL); g_free(m); return 1; } -static int gaim_parse_msgerr(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; -#if 0 +static int gaim_parse_msgerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; +#ifdef TODOFT OscarData *od = gc->proto_data; GaimXfer *xfer; #endif @@ -5151,8 +2716,7 @@ "Message error with data %s and reason %hu\n", (data != NULL ? data : ""), reason); -/* BBB */ -#if 0 +#ifdef TODOFT /* If this was a file transfer request, data is a cookie */ if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, data))) { gaim_xfer_cancel_remote(xfer); @@ -5165,7 +2729,7 @@ if (!gaim_conv_present_error(data, gaim_connection_get_account(gc), buf)) { g_free(buf); buf = g_strdup_printf(_("Unable to send message to %s:"), data ? data : "(unknown)"); - gaim_notify_error(sess->aux_data, NULL, buf, + gaim_notify_error(od->gc, NULL, buf, (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); } g_free(buf); @@ -5173,8 +2737,8 @@ return 1; } -static int gaim_parse_mtn(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_parse_mtn(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; guint16 type1, type2; char *sn; @@ -5210,7 +2774,7 @@ * We get this error when there was an error in the locate family. This * happens when you request info of someone who is offline. */ -static int gaim_parse_locerr(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_parse_locerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { gchar *buf; va_list ap; guint16 reason; @@ -5225,20 +2789,19 @@ return 1; buf = g_strdup_printf(_("User information not available: %s"), (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); - if (!gaim_conv_present_error(destn, gaim_connection_get_account((GaimConnection*)sess->aux_data), buf)) { + if (!gaim_conv_present_error(destn, gaim_connection_get_account((GaimConnection*)od->gc), buf)) { g_free(buf); buf = g_strdup_printf(_("User information for %s unavailable:"), destn); - gaim_notify_error(sess->aux_data, NULL, buf, (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); + gaim_notify_error(od->gc, NULL, buf, (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); } g_free(buf); return 1; } -static int gaim_parse_userinfo(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_parse_userinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; GaimAccount *account = gaim_connection_get_account(gc); - OscarData *od = gc->proto_data; GString *str; gchar *tmp = NULL, *info_utf8 = NULL, *away_utf8 = NULL; va_list ap; @@ -5317,9 +2880,9 @@ return 1; } -static int gaim_got_infoblock(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_got_infoblock(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; + GaimConnection *gc = od->gc; GaimBuddy *b; GaimPresence *presence; GaimStatus *status; @@ -5356,35 +2919,7 @@ return 1; } -static gboolean gaim_reqinfo_timeout_cb(void *data) -{ - OscarSession *sess = data; - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; - - aim_locate_dorequest(data); - od->getinfotimer = 0; - - return FALSE; -} - -static int gaim_reqinfo_timeout(OscarSession *sess, FlapFrame *fr, ...) -{ - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; - - /* - * Wait a little while then call aim_locate_dorequest(sess). This keeps - * us from hitting the rate limit due to request away messages and info - * too quickly. - */ - if (od->getinfotimer == 0) - od->getinfotimer = gaim_timeout_add(10000, gaim_reqinfo_timeout_cb, sess); - - return 1; -} - -static int gaim_parse_motd(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_parse_motd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { char *msg; guint16 id; @@ -5398,17 +2933,15 @@ gaim_debug_misc("oscar", "MOTD: %s (%hu)\n", msg ? msg : "Unknown", id); if (id < 4) - gaim_notify_warning(sess->aux_data, NULL, + gaim_notify_warning(od->gc, NULL, _("Your AIM connection may be lost."), NULL); return 1; } -static int gaim_chatnav_info(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_chatnav_info(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; guint16 type; - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; va_start(ap, fr); type = (guint16) va_arg(ap, unsigned int); @@ -5423,8 +2956,7 @@ exchangecount = va_arg(ap, int); exchanges = va_arg(ap, struct aim_chat_exchangeinfo *); - gaim_debug_misc("oscar", - "chat info: Chat Rights:\n"); + gaim_debug_misc("oscar", "chat info: Chat Rights:\n"); gaim_debug_misc("oscar", "chat info: \tMax Concurrent Rooms: %hhd\n", maxrooms); gaim_debug_misc("oscar", @@ -5437,7 +2969,7 @@ struct create_room *cr = od->create_rooms->data; gaim_debug_info("oscar", "creating room %s\n", cr->name); - aim_chatnav_createroom(sess, fr->conn, cr->name, cr->exchange); + aim_chatnav_createroom(od, conn, cr->name, cr->exchange); g_free(cr->name); od->create_rooms = g_slist_remove(od->create_rooms, cr); g_free(cr); @@ -5463,13 +2995,11 @@ ck = va_arg(ap, char *); gaim_debug_misc("oscar", - "created room: %s %hu %hu %hu %u %hu %hu %hhu %hu %s %s\n", - fqcn, - exchange, instance, flags, - createtime, + "created room: %s %hu %hu %hu %u %hu %hu %hhu %hu %s %s\n", + fqcn, exchange, instance, flags, createtime, maxmsglen, maxoccupancy, createperms, unknown, name, ck); - aim_chat_join(od->sess, od->conn, exchange, ck, instance); + aim_chat_join(od, exchange, ck, instance); } break; default: @@ -5483,11 +3013,11 @@ return 1; } -static int gaim_conv_chat_join(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_conv_chat_join(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; int count, i; aim_userinfo_t *info; - GaimConnection *g = sess->aux_data; + GaimConnection *gc = od->gc; struct chat_connection *c = NULL; @@ -5496,7 +3026,7 @@ info = va_arg(ap, aim_userinfo_t *); va_end(ap); - c = find_oscar_chat_by_conn(g, fr->conn); + c = find_oscar_chat_by_conn(gc, conn); if (!c) return 1; @@ -5506,11 +3036,11 @@ return 1; } -static int gaim_conv_chat_leave(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_conv_chat_leave(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; int count, i; aim_userinfo_t *info; - GaimConnection *g = sess->aux_data; + GaimConnection *gc = od->gc; struct chat_connection *c = NULL; @@ -5519,7 +3049,7 @@ info = va_arg(ap, aim_userinfo_t *); va_end(ap); - c = find_oscar_chat_by_conn(g, fr->conn); + c = find_oscar_chat_by_conn(gc, conn); if (!c) return 1; @@ -5529,7 +3059,7 @@ return 1; } -static int gaim_conv_chat_info_update(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_conv_chat_info_update(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; aim_userinfo_t *userinfo; struct aim_chat_roominfo *roominfo; @@ -5538,8 +3068,8 @@ char *roomdesc; guint16 unknown_c9, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen; guint32 creationtime; - GaimConnection *gc = sess->aux_data; - struct chat_connection *ccon = find_oscar_chat_by_conn(gc, fr->conn); + GaimConnection *gc = od->gc; + struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn); va_start(ap, fr); roominfo = va_arg(ap, struct aim_chat_roominfo *); @@ -5565,9 +3095,9 @@ return 1; } -static int gaim_conv_chat_incoming_msg(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - struct chat_connection *ccon = find_oscar_chat_by_conn(gc, fr->conn); +static int gaim_conv_chat_incoming_msg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; + struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn); gchar *utf8; va_list ap; aim_userinfo_t *info; @@ -5592,9 +3122,9 @@ return 1; } -static int gaim_email_parseupdate(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_email_parseupdate(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; - GaimConnection *gc = sess->aux_data; + GaimConnection *gc = od->gc; struct aim_emailinfo *emailinfo; int havenewmail; char *alertitle, *alerturl; @@ -5621,16 +3151,14 @@ return 1; } -static int gaim_icon_error(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; +static int gaim_icon_error(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; char *sn; sn = od->requesticon->data; - gaim_debug_misc("oscar", - "removing %s from hash table\n", sn); + gaim_debug_misc("oscar", "removing %s from hash table\n", sn); od->requesticon = g_slist_remove(od->requesticon, sn); - free(sn); + g_free(sn); if (od->icontimer) gaim_timeout_remove(od->icontimer); @@ -5639,9 +3167,8 @@ return 1; } -static int gaim_icon_parseicon(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; +static int gaim_icon_parseicon(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; GSList *cur; va_list ap; char *sn; @@ -5678,7 +3205,7 @@ char *cursn = cur->data; if (!aim_sncmp(cursn, sn)) { od->requesticon = g_slist_remove(od->requesticon, cursn); - free(cursn); + g_free(cursn); cur = od->requesticon; } else cur = cur->next; @@ -5695,12 +3222,12 @@ GaimConnection *gc = data; OscarData *od = gc->proto_data; aim_userinfo_t *userinfo; - OscarConnection *conn; - - conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_ICON); + FlapConnection *conn; + + conn = flap_connection_getbytype(od, SNAC_FAMILY_BART); if (!conn) { if (!od->iconconnecting) { - aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_ICON); + aim_reqservice(od, SNAC_FAMILY_BART); od->iconconnecting = TRUE; } return FALSE; @@ -5710,7 +3237,7 @@ struct stat st; char *iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(gaim_connection_get_account(gc))); if (iconfile == NULL) { - aim_ssi_delicon(od->sess); + aim_ssi_delicon(od); } else if (!g_stat(iconfile, &st)) { guchar *buf = g_malloc(st.st_size); FILE *file = g_fopen(iconfile, "rb"); @@ -5720,7 +3247,7 @@ fclose(file); gaim_debug_info("oscar", "Uploading icon to icon server\n"); - aim_bart_upload(od->sess, buf, st.st_size); + aim_bart_upload(od, buf, st.st_size); } else gaim_debug_error("oscar", "Can't open buddy icon file!\n"); @@ -5739,14 +3266,14 @@ return FALSE; } - userinfo = aim_locate_finduserinfo(od->sess, (char *)od->requesticon->data); + userinfo = aim_locate_finduserinfo(od, (char *)od->requesticon->data); if ((userinfo != NULL) && (userinfo->iconcsumlen > 0)) { - aim_bart_request(od->sess, od->requesticon->data, userinfo->iconcsumtype, userinfo->iconcsum, userinfo->iconcsumlen); + aim_bart_request(od, od->requesticon->data, userinfo->iconcsumtype, userinfo->iconcsum, userinfo->iconcsumlen); return FALSE; } else { - char *sn = od->requesticon->data; + gchar *sn = od->requesticon->data; od->requesticon = g_slist_remove(od->requesticon, sn); - free(sn); + g_free(sn); } return TRUE; @@ -5755,7 +3282,7 @@ /* * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option. */ -static int gaim_parse_msgack(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_parse_msgack(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; guint16 type; char *sn; @@ -5770,7 +3297,7 @@ return 1; } -static int gaim_parse_ratechange(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_parse_ratechange(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { static const char *codes[5] = { "invalid", "change", @@ -5806,7 +3333,7 @@ if (code == AIM_RATE_CODE_LIMIT) { - gaim_notify_error(sess->aux_data, NULL, _("Rate limiting error."), + gaim_notify_error(od->gc, NULL, _("Rate limiting error."), _("The last action you attempted could not be " "performed because you are over the rate limit. " "Please wait 10 seconds and try again.")); @@ -5815,7 +3342,7 @@ return 1; } -static int gaim_parse_evilnotify(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_parse_evilnotify(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; guint16 newevil; aim_userinfo_t *userinfo; @@ -5832,7 +3359,7 @@ return 1; } -static int gaim_selfinfo(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_selfinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { int warning_level; va_list ap; aim_userinfo_t *info; @@ -5857,9 +3384,8 @@ return 1; } -static int gaim_connerr(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; +static int gaim_connerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; guint16 code; char *msg; @@ -5873,9 +3399,9 @@ code, (msg != NULL ? msg : "")); g_return_val_if_fail(fr != NULL, 1); - g_return_val_if_fail(fr->conn != NULL, 1); - - if (fr->conn->type == AIM_CONN_TYPE_BOS) { + g_return_val_if_fail(conn != NULL, 1); + + if (conn->type == SNAC_FAMILY_LOCATE) { if (code == 0x0001) { gc->wants_to_die = TRUE; gaim_connection_error(gc, _("You have signed on from another location.")); @@ -5883,11 +3409,11 @@ gaim_connection_error(gc, _("You have been signed off for an unknown reason.")); } od->killme = TRUE; - } else if (fr->conn->type == AIM_CONN_TYPE_CHAT) { + } else if (conn->type == SNAC_FAMILY_CHAT) { struct chat_connection *cc; GaimConversation *conv; - cc = find_oscar_chat_by_conn(gc, fr->conn); + cc = find_oscar_chat_by_conn(gc, conn); conv = gaim_find_chat(gc, cc->id); if (conv != NULL) @@ -5904,78 +3430,7 @@ return 1; } -static int conninitdone_bos(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; - - aim_reqpersonalinfo(sess, fr->conn); - - gaim_debug_info("oscar", "ssi: requesting rights and list\n"); - aim_ssi_reqrights(sess); - aim_ssi_reqdata(sess); - if (od->getblisttimer > 0) - gaim_timeout_remove(od->getblisttimer); - od->getblisttimer = gaim_timeout_add(30000, gaim_ssi_rerequestdata, od->sess); - - aim_locate_reqrights(sess); - aim_buddylist_reqrights(sess, fr->conn); - aim_im_reqparams(sess); - aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi */ - - gaim_connection_update_progress(gc, _("Finalizing connection"), 5, OSCAR_CONNECT_STEPS); - - return 1; -} - -static int conninitdone_admin(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; - - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_ADMIN, 0x0003, gaim_info_change, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_ADMIN, 0x0005, gaim_info_change, 0); - aim_conn_addhandler(sess, fr->conn, OSCAR_FAMILY_ADMIN, 0x0007, gaim_account_confirm, 0); - - aim_clientready(sess, fr->conn); - gaim_debug_info("oscar", "connected to admin\n"); - - if (od->chpass) { - gaim_debug_info("oscar", "changing password\n"); - aim_admin_changepasswd(sess, fr->conn, od->newp, od->oldp); - g_free(od->oldp); - od->oldp = NULL; - g_free(od->newp); - od->newp = NULL; - od->chpass = FALSE; - } - if (od->setnick) { - gaim_debug_info("oscar", "formatting screen name\n"); - aim_admin_setnick(sess, fr->conn, od->newsn); - g_free(od->newsn); - od->newsn = NULL; - od->setnick = FALSE; - } - if (od->conf) { - gaim_debug_info("oscar", "confirming account\n"); - aim_admin_reqconfirm(sess, fr->conn); - od->conf = FALSE; - } - if (od->reqemail) { - gaim_debug_info("oscar", "requesting email\n"); - aim_admin_getinfo(sess, fr->conn, 0x0011); - od->reqemail = FALSE; - } - if (od->setemail) { - gaim_debug_info("oscar", "setting email\n"); - aim_admin_setemail(sess, fr->conn, od->email); - g_free(od->email); - od->email = NULL; - od->setemail = FALSE; - } - - return 1; -} - -static int gaim_icbm_param_info(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_icbm_param_info(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { struct aim_icbmparameters *params; va_list ap; @@ -5996,16 +3451,15 @@ params->maxmsglen = 8000; params->minmsginterval = 0; - aim_im_setparams(sess, params); + aim_im_setparams(od, params); return 1; } -static int gaim_parse_locaterights(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_parse_locaterights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; + GaimConnection *gc = od->gc; GaimAccount *account = gaim_connection_get_account(gc); - OscarData *od = (OscarData *)gc->proto_data; va_list ap; guint16 maxsiglen; @@ -6019,20 +3473,18 @@ od->rights.maxsiglen = od->rights.maxawaymsglen = (guint)maxsiglen; if (od->icq) - aim_locate_setcaps(od->sess, caps_icq); + aim_locate_setcaps(od, caps_icq); else - aim_locate_setcaps(od->sess, caps_aim); + aim_locate_setcaps(od, caps_aim); oscar_set_info_and_status(account, TRUE, account->user_info, TRUE, gaim_account_get_active_status(account)); return 1; } -static int gaim_parse_buddyrights(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_parse_buddyrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; guint16 maxbuddies, maxwatchers; - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; va_start(ap, fr); maxbuddies = (guint16) va_arg(ap, unsigned int); @@ -6048,9 +3500,8 @@ return 1; } -static int gaim_bosrights(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_bosrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { GaimConnection *gc; - OscarData *od; GaimAccount *account; GaimStatus *status; const char *message; @@ -6058,7 +3509,7 @@ va_list ap; guint16 maxpermits, maxdenies; - gc = sess->aux_data; + gc = od->gc; od = (OscarData *)gc->proto_data; account = gaim_connection_get_account(gc); @@ -6077,7 +3528,7 @@ gaim_debug_info("oscar", "buddy list loaded\n"); - aim_clientready(sess, fr->conn); + aim_clientready(od, conn); /* Set our available message based on the current status */ status = gaim_account_get_active_status(account); @@ -6086,27 +3537,27 @@ else message = NULL; tmp = gaim_markup_strip_html(message); - aim_srv_setstatusmsg(sess, tmp); - free(tmp); - - aim_srv_setidle(sess, 0); + aim_srv_setstatusmsg(od, tmp); + g_free(tmp); + + aim_srv_setidle(od, 0); if (od->icq) { - aim_icq_reqofflinemsgs(sess); + aim_icq_reqofflinemsgs(od); oscar_set_extendedstatus(gc); - aim_icq_setsecurity(sess, + aim_icq_setsecurity(od, gaim_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION), gaim_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE)); } - aim_reqservice(sess, fr->conn, AIM_CONN_TYPE_CHATNAV); - if (sess->authinfo->email) - aim_reqservice(sess, fr->conn, AIM_CONN_TYPE_EMAIL); + aim_reqservice(od, SNAC_FAMILY_CHATNAV); + if (od->authinfo->email != NULL) + aim_reqservice(od, SNAC_FAMILY_ALERT); return 1; } -static int gaim_offlinemsg(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_offlinemsg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; struct aim_icq_offlinemsg *msg; struct aim_incomingim_ch4_args args; @@ -6124,21 +3575,20 @@ args.msglen = msg->msglen; args.msg = msg->msg; t = gaim_time_build(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); - incomingim_chan4(sess, fr->conn, NULL, &args, t); + incomingim_chan4(od, conn, NULL, &args, t); return 1; } -static int gaim_offlinemsgdone(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_offlinemsgdone(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - aim_icq_ackofflinemsgs(sess); + aim_icq_ackofflinemsgs(od); return 1; } -static int gaim_icqinfo(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_icqinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; + GaimConnection *gc = od->gc; GaimBuddy *buddy; struct buddyinfo *bi = NULL; gchar who[16]; @@ -6250,9 +3700,9 @@ return 1; } -static int gaim_icqalias(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_icqalias(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; + GaimConnection *gc = od->gc; GaimAccount *account = gaim_connection_get_account(gc); gchar who[16], *utf8; GaimBuddy *b; @@ -6275,9 +3725,9 @@ return 1; } -static int gaim_popup(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_popup(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; + GaimConnection *gc = od->gc; gchar *text; va_list ap; char *msg, *url; @@ -6304,9 +3754,9 @@ g_list_nth_data(row, 0), NULL, NULL); } -static int gaim_parse_searchreply(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_parse_searchreply(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; + GaimConnection *gc = od->gc; GaimNotifySearchResults *results; GaimNotifySearchColumn *column; gchar *secondary; @@ -6337,7 +3787,7 @@ num), email); - column = gaim_notify_searchresults_column_new(_("Screen Name")); + column = gaim_notify_searchresults_column_new(_("Screen name")); gaim_notify_searchresults_column_add(results, column); for (i = 0; i < num; i++) { @@ -6354,7 +3804,7 @@ return 1; } -static int gaim_parse_searcherror(OscarSession *sess, FlapFrame *fr, ...) { +static int gaim_parse_searcherror(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; char *email; char *buf; @@ -6364,14 +3814,14 @@ va_end(ap); buf = g_strdup_printf(_("No results found for e-mail address %s"), email); - gaim_notify_error(sess->aux_data, NULL, buf, NULL); + gaim_notify_error(od->gc, NULL, buf, NULL); g_free(buf); return 1; } -static int gaim_account_confirm(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_account_confirm(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; guint16 status; va_list ap; char msg[256]; @@ -6382,7 +3832,7 @@ gaim_debug_info("oscar", "account confirmation returned status 0x%04x (%s)\n", status, - status ? "unknown" : "email sent"); + status ? "unknown" : "e-mail sent"); if (!status) { g_snprintf(msg, sizeof(msg), _("You should receive an e-mail asking to confirm %s."), gaim_account_get_username(gaim_connection_get_account(gc))); @@ -6392,8 +3842,8 @@ return 1; } -static int gaim_info_change(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_info_change(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; guint16 perms, err; char *url, *sn, *email; @@ -6463,21 +3913,31 @@ return 1; } -static void oscar_keepalive(GaimConnection *gc) { - OscarData *od = (OscarData *)gc->proto_data; - aim_flap_nop(od->sess, od->conn); -} - -static int oscar_send_typing(GaimConnection *gc, const char *name, int typing) { - OscarData *od = (OscarData *)gc->proto_data; - struct oscar_direct_im *dim = oscar_direct_im_find(od, name); - if (dim && dim->connected) - if (typing == GAIM_TYPING) - aim_odc_send_typing(od->sess, dim->conn, 0x0002); - else if (typing == GAIM_TYPED) - aim_odc_send_typing(od->sess, dim->conn, 0x0001); - else - aim_odc_send_typing(od->sess, dim->conn, 0x0000); +static void +oscar_keepalive(GaimConnection *gc) +{ + OscarData *od; + FlapConnection *conn; + + od = (OscarData *)gc->proto_data; + conn = flap_connection_getbytype(od, SNAC_FAMILY_LOCATE); + if (conn != NULL) + flap_connection_send_keepalive(od, conn); +} + +static int +oscar_send_typing(GaimConnection *gc, const char *name, int typing) +{ + OscarData *od; + PeerConnection *conn; + + od = (OscarData *)gc->proto_data; + conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM); + + if ((conn != NULL) && (conn->ready)) + { + peer_odc_send_typing(conn, typing); + } else { /* Don't send if this turkey is in our deny list */ GSList *list; @@ -6486,41 +3946,116 @@ struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, name)); if (bi && bi->typingnot) { if (typing == GAIM_TYPING) - aim_im_sendmtn(od->sess, 0x0001, name, 0x0002); + aim_im_sendmtn(od, 0x0001, name, 0x0002); else if (typing == GAIM_TYPED) - aim_im_sendmtn(od->sess, 0x0001, name, 0x0001); + aim_im_sendmtn(od, 0x0001, name, 0x0001); else - aim_im_sendmtn(od->sess, 0x0001, name, 0x0000); + aim_im_sendmtn(od, 0x0001, name, 0x0000); } } } return 0; } -static int gaim_odc_send_im(OscarSession *, OscarConnection *, const char *, GaimMessageFlags); - -static int oscar_send_im(GaimConnection *gc, const char *name, const char *message, GaimMessageFlags imflags) { - OscarData *od = (OscarData *)gc->proto_data; - GaimAccount *account = gaim_connection_get_account(gc); - struct oscar_direct_im *dim = oscar_direct_im_find(od, name); - int ret = 0; - char *iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(account)); +/* TODO: Move this into odc.c! */ +static void +gaim_odc_send_im(PeerConnection *conn, const char *message, GaimMessageFlags imflags) +{ + GString *msg = g_string_new("<HTML><BODY>"); + GString *data = g_string_new("</BODY></HTML><BINARY>"); + GData *attribs; + const char *start, *end, *last; + int oscar_id = 0; + + last = message; + + /* for each valid IMG tag... */ + while (last && *last && gaim_markup_find_tag("img", last, &start, &end, &attribs)) + { + GaimStoredImage *image = NULL; + const char *id; + + if (start - last) { + g_string_append_len(msg, last, start - last); + } + + id = g_datalist_get_data(&attribs, "id"); + + /* ... if it refers to a valid gaim image ... */ + if (id && (image = gaim_imgstore_get(atoi(id)))) { + /* ... append the message from start to the tag ... */ + unsigned long size = gaim_imgstore_get_size(image); + const char *filename = gaim_imgstore_get_filename(image); + gpointer imgdata = gaim_imgstore_get_data(image); + + oscar_id++; + + /* ... insert a new img tag with the oscar id ... */ + if (filename) + g_string_append_printf(msg, + "<IMG SRC=\"%s\" ID=\"%d\" DATASIZE=\"%lu\">", + filename, oscar_id, size); + else + g_string_append_printf(msg, + "<IMG ID=\"%d\" DATASIZE=\"%lu\">", + oscar_id, size); + + /* ... and append the data to the binary section ... */ + g_string_append_printf(data, "<DATA ID=\"%d\" SIZE=\"%lu\">", + oscar_id, size); + data = g_string_append_len(data, imgdata, size); + data = g_string_append(data, "</DATA>"); + } + /* If the tag is invalid, skip it, thus no else here */ + + g_datalist_clear(&attribs); + + /* continue from the end of the tag */ + last = end + 1; + } + + /* append any remaining message data (without the > :-) ) */ + if (last && *last) + msg = g_string_append(msg, last); + + /* if we inserted any images in the binary section, append it */ + if (oscar_id) { + msg = g_string_append_len(msg, data->str, data->len); + msg = g_string_append(msg, "</BINARY>"); + } + + g_string_free(data, TRUE); + + /* TODO: Deal with the encoding. */ + peer_odc_send_im(conn, msg->str, msg->len, 0, imflags & GAIM_MESSAGE_AUTO_RESP); + g_string_free(msg, TRUE); +} + +static int +oscar_send_im(GaimConnection *gc, const char *name, const char *message, GaimMessageFlags imflags) +{ + OscarData *od; + GaimAccount *account; + PeerConnection *conn; + int ret; + char *iconfile; char *tmp1, *tmp2; + od = (OscarData *)gc->proto_data; + account = gaim_connection_get_account(gc); + ret = 0; + iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(account)); + if (imflags & GAIM_MESSAGE_AUTO_RESP) - /* - * TODO: Do this earlier in the IM-sending chain of events. - * We should attach to an IM-sending signal and do it - * there. As it is currently implemented, encrypted - * messages are not substituted. - */ tmp1 = gaim_str_sub_away_formatters(message, name); else tmp1 = g_strdup(message); - if (dim && dim->connected) { + conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM); + if ((conn != NULL) && (conn->ready)) + { /* If we're directly connected, send a direct IM */ - ret = gaim_odc_send_im(od->sess, dim->conn, tmp1, imflags); + gaim_odc_send_im(conn, tmp1, imflags); } else { struct buddyinfo *bi; struct aim_sendimext_args args; @@ -6579,7 +4114,7 @@ FILE *file = g_fopen(iconfile, "rb"); if (file) { guchar *buf = g_malloc(st.st_size); - /* XXX - Use g_file_get_contents()? */ + /* TODO: Use g_file_get_contents()? */ fread(buf, 1, st.st_size, file); fclose(file); @@ -6633,7 +4168,7 @@ gaim_plugin_oscar_convert_to_best_encoding(gc, name, tmp1, (char **)&args.msg, &args.msglen, &args.charset, &args.charsubset); gaim_debug_info("oscar", "Sending IM, charset=0x%04hx, charsubset=0x%04hx, length=%d\n", args.charset, args.charsubset, args.msglen); - ret = aim_im_sendch1_ext(od->sess, &args); + ret = aim_im_sendch1_ext(od, &args); g_free((char *)args.msg); } @@ -6649,9 +4184,9 @@ OscarData *od = (OscarData *)gc->proto_data; if (od->icq && aim_sn_is_icq(name)) - aim_icq_getallinfo(od->sess, name); + aim_icq_getallinfo(od, name); else - aim_locate_getinfoshort(od->sess, name, 0x00000003); + aim_locate_getinfoshort(od, name, 0x00000003); } #if 0 @@ -6659,14 +4194,14 @@ const char *maiden, const char *city, const char *state, const char *country, int web) { /* XXX - some of these things are wrong, but i'm lazy */ OscarData *od = (OscarData *)gc->proto_data; - aim_locate_setdirinfo(od->sess, first, middle, last, + aim_locate_setdirinfo(od, first, middle, last, maiden, NULL, NULL, city, state, NULL, 0, web); } #endif static void oscar_set_idle(GaimConnection *gc, int time) { OscarData *od = (OscarData *)gc->proto_data; - aim_srv_setidle(od->sess, time); + aim_srv_setidle(od, time); } static @@ -6737,7 +4272,7 @@ else if (!strcmp(status_id, OSCAR_STATUS_ID_CUSTOM)) data |= AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY; - aim_setextstatus(od->sess, data); + aim_setextstatus(od, data); } static void @@ -6816,15 +4351,14 @@ char *tmp = g_utf8_find_prev_char(status_text, &status_text[58]); strcpy(tmp, "..."); } + else + { + /* User did not specify an available message */ + status_text = NULL; + } + aim_srv_setstatusmsg(od, status_text); + g_free(status_text); } - else - { - /* User did not specify an available message */ - status_text = NULL; - } - - aim_srv_setstatusmsg(od->sess, status_text); - g_free(status_text); /* This is needed for us to un-set any previous away message. */ away = g_strdup(""); @@ -6853,7 +4387,7 @@ if (setstatus) oscar_set_extendedstatus(gc); - aim_locate_setprofile(od->sess, info_encoding, info, MIN(infolen, od->rights.maxsiglen), + aim_locate_setprofile(od, info_encoding, info, MIN(infolen, od->rights.maxsiglen), away_encoding, away, MIN(awaylen, od->rights.maxawaymsglen)); g_free(info); g_free(away); @@ -6875,8 +4409,8 @@ else account->perm_deny = GAIM_PRIVACY_DENY_USERS; - if ((od->sess->ssi.received_data) && (aim_ssi_getpermdeny(od->sess->ssi.local) != account->perm_deny)) - aim_ssi_setpermdeny(od->sess, account->perm_deny, 0xffffffff); + if ((od->ssi.received_data) && (aim_ssi_getpermdeny(od->ssi.local) != account->perm_deny)) + aim_ssi_setpermdeny(od, account->perm_deny, 0xffffffff); oscar_set_extendedstatus(gc); } @@ -6904,7 +4438,7 @@ static void oscar_warn(GaimConnection *gc, const char *name, gboolean anonymous) { OscarData *od = (OscarData *)gc->proto_data; - aim_im_warn(od->sess, od->conn, name, anonymous ? AIM_WARN_ANON : 0); + aim_im_warn(od, od->conn, name, anonymous ? AIM_WARN_ANON : 0); } #endif @@ -6925,46 +4459,46 @@ return; } - if ((od->sess->ssi.received_data) && !(aim_ssi_itemlist_finditem(od->sess->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY))) { + if ((od->ssi.received_data) && !(aim_ssi_itemlist_finditem(od->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY))) { if (buddy && group) { gaim_debug_info("oscar", "ssi: adding buddy %s to group %s\n", buddy->name, group->name); - aim_ssi_addbuddy(od->sess, buddy->name, group->name, gaim_buddy_get_alias_only(buddy), NULL, NULL, 0); + aim_ssi_addbuddy(od, buddy->name, group->name, gaim_buddy_get_alias_only(buddy), NULL, NULL, 0); } } /* XXX - Should this be done from AIM accounts, as well? */ if (od->icq) - aim_icq_getalias(od->sess, buddy->name); + aim_icq_getalias(od, buddy->name); } static void oscar_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) { OscarData *od = (OscarData *)gc->proto_data; - if (od->sess->ssi.received_data) { + if (od->ssi.received_data) { gaim_debug_info("oscar", "ssi: deleting buddy %s from group %s\n", buddy->name, group->name); - aim_ssi_delbuddy(od->sess, buddy->name, group->name); + aim_ssi_delbuddy(od, buddy->name, group->name); } } static void oscar_move_buddy(GaimConnection *gc, const char *name, const char *old_group, const char *new_group) { OscarData *od = (OscarData *)gc->proto_data; - if (od->sess->ssi.received_data && strcmp(old_group, new_group)) { + if (od->ssi.received_data && strcmp(old_group, new_group)) { gaim_debug_info("oscar", "ssi: moving buddy %s from group %s to group %s\n", name, old_group, new_group); - aim_ssi_movebuddy(od->sess, old_group, new_group, name); + aim_ssi_movebuddy(od, old_group, new_group, name); } } static void oscar_alias_buddy(GaimConnection *gc, const char *name, const char *alias) { OscarData *od = (OscarData *)gc->proto_data; - if (od->sess->ssi.received_data) { - char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, name); + if (od->ssi.received_data) { + char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); if (gname) { gaim_debug_info("oscar", "ssi: changing the alias for buddy %s to %s\n", name, alias ? alias : "(none)"); - aim_ssi_aliasbuddy(od->sess, gname, name, alias); + aim_ssi_aliasbuddy(od, gname, name, alias); } } } @@ -6975,8 +4509,8 @@ static void oscar_rename_group(GaimConnection *gc, const char *old_name, GaimGroup *group, GList *moved_buddies) { OscarData *od = (OscarData *)gc->proto_data; - if (od->sess->ssi.received_data) { - if (aim_ssi_itemlist_finditem(od->sess->ssi.local, group->name, NULL, AIM_SSI_TYPE_GROUP)) { + if (od->ssi.received_data) { + if (aim_ssi_itemlist_finditem(od->ssi.local, group->name, NULL, AIM_SSI_TYPE_GROUP)) { GList *cur, *groups = NULL; GaimAccount *account = gaim_connection_get_account(gc); @@ -6995,7 +4529,7 @@ gaim_debug_info("oscar", "ssi: moved all buddies from group %s to %s\n", old_name, group->name); } else { - aim_ssi_rename_group(od->sess, old_name, group->name); + aim_ssi_rename_group(od, old_name, group->name); gaim_debug_info("oscar", "ssi: renamed group %s to %s\n", old_name, group->name); } @@ -7003,16 +4537,15 @@ } static gboolean gaim_ssi_rerequestdata(gpointer data) { - OscarSession *sess = data; - - aim_ssi_reqdata(sess); + OscarData *od = data; + + aim_ssi_reqdata(od); return TRUE; } -static int gaim_ssi_parseerr(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; +static int gaim_ssi_parseerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; guint16 reason; @@ -7027,7 +4560,7 @@ _("Gaim was temporarily unable to retrieve your buddy list from the AIM servers. Your buddy list is not lost, and will probably become available in a few hours.")); if (od->getblisttimer > 0) gaim_timeout_remove(od->getblisttimer); - od->getblisttimer = gaim_timeout_add(30000, gaim_ssi_rerequestdata, od->sess); + od->getblisttimer = gaim_timeout_add(30000, gaim_ssi_rerequestdata, od); } oscar_set_extendedstatus(gc); @@ -7036,14 +4569,12 @@ /* Sending the enable causes other people to be able to see you, and you to see them */ /* Make sure your privacy setting/invisibility is set how you want it before this! */ gaim_debug_info("oscar", "ssi: activating server-stored buddy list\n"); - aim_ssi_enable(od->sess); + aim_ssi_enable(od); return 1; } -static int gaim_ssi_parserights(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = (OscarData *)gc->proto_data; +static int gaim_ssi_parserights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { int i; va_list ap; int numtypes; @@ -7074,10 +4605,9 @@ return 1; } -static int gaim_ssi_parselist(OscarSession *sess, FlapFrame *fr, ...) +static int gaim_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { GaimConnection *gc; - OscarData *od; GaimAccount *account; GaimGroup *g; GaimBuddy *b; @@ -7088,7 +4618,7 @@ struct aim_ssi_item *items; guint32 timestamp; - gc = sess->aux_data; + gc = od->gc; od = gc->proto_data; account = gaim_connection_get_account(gc); @@ -7113,7 +4643,7 @@ } /* Clean the buddy list */ - aim_ssi_cleanlist(sess); + aim_ssi_cleanlist(od); { /* If not in server list then prune from local list */ GaimBlistNode *gnode, *cnode, *bnode; @@ -7135,7 +4665,7 @@ continue; b = (GaimBuddy *)bnode; if (b->account == gc->account) { - if (aim_ssi_itemlist_exists(sess->ssi.local, b->name)) { + if (aim_ssi_itemlist_exists(od->ssi.local, b->name)) { /* If the buddy is an ICQ user then load his nickname */ const char *servernick = gaim_blist_node_get_string((GaimBlistNode*)b, "servernick"); char *alias; @@ -7143,10 +4673,10 @@ serv_got_alias(gc, b->name, servernick); /* Store local alias on server */ - alias = aim_ssi_getalias(sess->ssi.local, g->name, b->name); + alias = aim_ssi_getalias(od->ssi.local, g->name, b->name); if (!alias && b->alias && strlen(b->alias)) - aim_ssi_aliasbuddy(sess, g->name, b->name, b->alias); - free(alias); + aim_ssi_aliasbuddy(od, g->name, b->name, b->alias); + g_free(alias); } else { gaim_debug_info("oscar", "ssi: removing buddy %s from local list\n", b->name); @@ -7171,7 +4701,7 @@ while (next != NULL) { cur = next; next = next->next; - if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) { + if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) { gaim_debug_info("oscar", "ssi: removing permit %s from local list\n", (const char *)cur->data); gaim_privacy_permit_remove(account, cur->data, TRUE); @@ -7185,7 +4715,7 @@ while (next != NULL) { cur = next; next = next->next; - if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_DENY)) { + if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_DENY)) { gaim_debug_info("oscar", "ssi: removing deny %s from local list\n", (const char *)cur->data); gaim_privacy_deny_remove(account, cur->data, TRUE); @@ -7193,25 +4723,25 @@ } } /* Presence settings (idle time visibility) */ - if ((tmp = aim_ssi_getpresence(sess->ssi.local)) != 0xFFFFFFFF) + if ((tmp = aim_ssi_getpresence(od->ssi.local)) != 0xFFFFFFFF) if (!(tmp & 0x400)) - aim_ssi_setpresence(sess, tmp | 0x400); + aim_ssi_setpresence(od, tmp | 0x400); } /* end pruning buddies from local list */ /* Add from server list to local list */ - for (curitem=sess->ssi.local; curitem; curitem=curitem->next) { + for (curitem=od->ssi.local; curitem; curitem=curitem->next) { if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL))) switch (curitem->type) { case 0x0000: { /* Buddy */ if (curitem->name) { - char *gname = aim_ssi_itemlist_findparentname(sess->ssi.local, curitem->name); + char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, curitem->name); char *gname_utf8 = gname ? oscar_utf8_try_convert(gc->account, gname) : NULL; - char *alias = aim_ssi_getalias(sess->ssi.local, gname, curitem->name); + char *alias = aim_ssi_getalias(od->ssi.local, gname, curitem->name); char *alias_utf8 = alias ? oscar_utf8_try_convert(gc->account, alias) : NULL; b = gaim_find_buddy(gc->account, curitem->name); /* Should gname be freed here? -- elb */ /* Not with the current code, but that might be cleaner -- med */ - free(alias); + g_free(alias); if (b) { /* Get server stored alias */ if (alias_utf8) { @@ -7231,9 +4761,9 @@ gaim_blist_add_buddy(b, NULL, g, NULL); } if (!aim_sncmp(curitem->name, account->username)) { - char *comment = aim_ssi_getcomment(sess->ssi.local, gname, curitem->name); + char *comment = aim_ssi_getcomment(od->ssi.local, gname, curitem->name); gaim_check_comment(od, comment); - free(comment); + g_free(comment); } g_free(gname_utf8); g_free(alias_utf8); @@ -7272,7 +4802,7 @@ case 0x0004: { /* Permit/deny setting */ if (curitem->data) { guint8 permdeny; - if ((permdeny = aim_ssi_getpermdeny(sess->ssi.local)) && (permdeny != account->perm_deny)) { + if ((permdeny = aim_ssi_getpermdeny(od->ssi.local)) && (permdeny != account->perm_deny)) { gaim_debug_info("oscar", "ssi: changing permdeny from %d to %hhu\n", account->perm_deny, permdeny); account->perm_deny = permdeny; @@ -7296,13 +4826,13 @@ /* Make sure your privacy setting/invisibility is set how you want it before this! */ gaim_debug_info("oscar", "ssi: activating server-stored buddy list\n"); - aim_ssi_enable(sess); + aim_ssi_enable(od); return 1; } -static int gaim_ssi_parseack(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_ssi_parseack(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; struct aim_ssi_tmp *retval; @@ -7328,7 +4858,7 @@ } case 0x000e: { /* buddy requires authorization */ - if ((retval->action == OSCAR_SUBTYPE_FEEDBAG_ADD) && (retval->name)) + if ((retval->action == SNAC_SUBTYPE_FEEDBAG_ADD) && (retval->name)) gaim_auth_sendrequest(gc, retval->name); } break; @@ -7348,8 +4878,8 @@ return 1; } -static int gaim_ssi_parseadd(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_ssi_parseadd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; char *gname, *gname_utf8, *alias, *alias_utf8; GaimBuddy *b; GaimGroup *g; @@ -7365,12 +4895,12 @@ if ((type != 0x0000) || (name == NULL)) return 1; - gname = aim_ssi_itemlist_findparentname(sess->ssi.local, name); + gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); gname_utf8 = gname ? oscar_utf8_try_convert(gc->account, gname) : NULL; - alias = aim_ssi_getalias(sess->ssi.local, gname, name); + alias = aim_ssi_getalias(od->ssi.local, gname, name); alias_utf8 = alias ? oscar_utf8_try_convert(gc->account, alias) : NULL; b = gaim_find_buddy(gc->account, name); - free(alias); + g_free(alias); if (b) { /* Get server stored alias */ @@ -7396,8 +4926,8 @@ return 1; } -static int gaim_ssi_authgiven(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_ssi_authgiven(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; char *sn, *msg; gchar *dialog_msg, *nombre; @@ -7435,8 +4965,8 @@ return 1; } -static int gaim_ssi_authrequest(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_ssi_authrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; char *sn; char *msg; @@ -7488,8 +5018,8 @@ return 1; } -static int gaim_ssi_authreply(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_ssi_authreply(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; char *sn, *msg; gchar *dialog_msg, *nombre; @@ -7526,8 +5056,8 @@ return 1; } -static int gaim_ssi_gotadded(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; +static int gaim_ssi_gotadded(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; char *sn; GaimBuddy *buddy; @@ -7537,8 +5067,7 @@ va_end(ap); buddy = gaim_find_buddy(gc->account, sn); - gaim_debug_info("oscar", - "ssi: %s added you to their buddy list\n", sn); + gaim_debug_info("oscar", "ssi: %s added you to their buddy list\n", sn); gaim_account_notify_added(gc->account, NULL, sn, (buddy ? gaim_buddy_get_alias_only(buddy) : NULL), NULL); return 1; @@ -7578,13 +5107,17 @@ return defaults; } -static char *oscar_get_chat_name(GHashTable *data) { +static char * +oscar_get_chat_name(GHashTable *data) +{ return g_strdup(g_hash_table_lookup(data, "room")); } -static void oscar_join_chat(GaimConnection *gc, GHashTable *data) { +static void +oscar_join_chat(GaimConnection *gc, GHashTable *data) +{ OscarData *od = (OscarData *)gc->proto_data; - OscarConnection *cur; + FlapConnection *conn; char *name, *exchange; name = g_hash_table_lookup(data, "room"); @@ -7595,33 +5128,33 @@ return; } - gaim_debug_info("oscar", - "Attempting to join chat room %s.\n", name); - - if ((cur = aim_getconn_type(od->sess, AIM_CONN_TYPE_CHATNAV))) { - gaim_debug_info("oscar", - "chatnav exists, creating room\n"); - aim_chatnav_createroom(od->sess, cur, name, atoi(exchange)); + gaim_debug_info("oscar", "Attempting to join chat room %s.\n", name); + + if ((conn = flap_connection_getbytype(od, SNAC_FAMILY_CHATNAV))) + { + gaim_debug_info("oscar", "chatnav exists, creating room\n"); + aim_chatnav_createroom(od, conn, name, atoi(exchange)); } else { /* this gets tricky */ struct create_room *cr = g_new0(struct create_room, 1); - gaim_debug_info("oscar", - "chatnav does not exist, opening chatnav\n"); + gaim_debug_info("oscar", "chatnav does not exist, opening chatnav\n"); cr->exchange = atoi(exchange); cr->name = g_strdup(name); od->create_rooms = g_slist_append(od->create_rooms, cr); - aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_CHATNAV); - } -} - -static void oscar_chat_invite(GaimConnection *gc, int id, const char *message, const char *name) { + aim_reqservice(od, SNAC_FAMILY_CHATNAV); + } +} + +static void +oscar_chat_invite(GaimConnection *gc, int id, const char *message, const char *name) +{ OscarData *od = (OscarData *)gc->proto_data; struct chat_connection *ccon = find_oscar_chat(gc, id); if (ccon == NULL) return; - aim_im_sendch2_chatinvite(od->sess, name, message ? message : "", + aim_im_sendch2_chatinvite(od, name, message ? message : "", ccon->exchange, ccon->name, 0x0); } @@ -7677,7 +5210,7 @@ charsetstr = "unicode-2-0"; else if (charset == AIM_CHARSET_CUSTOM) charsetstr = "iso-8859-1"; - aim_chat_send_im(od->sess, c->conn, 0, buf2, len, charsetstr, "en"); + aim_chat_send_im(od, c->conn, 0, buf2, len, charsetstr, "en"); g_free(buf2); return 0; @@ -7716,7 +5249,7 @@ if (gc != NULL) od = gc->proto_data; if (od != NULL) - userinfo = aim_locate_finduserinfo(od->sess, b->name); + userinfo = aim_locate_finduserinfo(od, b->name); presence = gaim_buddy_get_presence(b); status = gaim_presence_get_active_status(presence); @@ -7724,9 +5257,9 @@ if (gaim_presence_is_online(presence) == FALSE) { char *gname; - if ((b->name) && (od) && (od->sess->ssi.received_data) && - (gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name)) && - (aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name))) { + if ((b->name) && (od) && (od->ssi.received_data) && + (gname = aim_ssi_itemlist_findparentname(od->ssi.local, b->name)) && + (aim_ssi_waitingforauth(od->ssi.local, gname, b->name))) { emblems[i++] = "notauthorized"; } else { emblems[i++] = "offline"; @@ -7762,10 +5295,10 @@ if ((i < 4) && userinfo->flags & AIM_FLAG_ACTIVEBUDDY) emblems[i++] = "activebuddy"; - if ((i < 4) && (userinfo->capabilities & AIM_CAPS_HIPTOP)) + if ((i < 4) && (userinfo->capabilities & OSCAR_CAPABILITY_HIPTOP)) emblems[i++] = "hiptop"; - if ((i < 4) && (userinfo->capabilities & AIM_CAPS_SECUREIM)) + if ((i < 4) && (userinfo->capabilities & OSCAR_CAPABILITY_SECUREIM)) emblems[i++] = "secure"; } @@ -7778,7 +5311,7 @@ static void oscar_tooltip_text(GaimBuddy *b, GString *str, gboolean full) { GaimConnection *gc = b->account->gc; OscarData *od = gc->proto_data; - aim_userinfo_t *userinfo = aim_locate_finduserinfo(od->sess, b->name); + aim_userinfo_t *userinfo = aim_locate_finduserinfo(od, b->name); if (GAIM_BUDDY_IS_ONLINE(b)) { GaimPresence *presence; @@ -7796,8 +5329,9 @@ { if (message != NULL) { - char *tmp = g_markup_escape_text(message, -1); /* Available status messages are plain text */ + gchar *tmp; + tmp = g_markup_escape_text(message, -1); g_string_append_printf(str, "\n<b>%s:</b> %s", _("Message"), tmp); g_free(tmp); } @@ -7844,8 +5378,8 @@ if (!gaim_presence_is_online(presence)) { - char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, b->name); - if (aim_ssi_waitingforauth(od->sess->ssi.local, gname, b->name)) + char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, b->name); + if (aim_ssi_waitingforauth(od->ssi.local, gname, b->name)) ret = g_strdup(_("Not Authorized")); else ret = g_strdup(_("Offline")); @@ -7886,9 +5420,8 @@ } -static int oscar_icon_req(OscarSession *sess, FlapFrame *fr, ...) { - GaimConnection *gc = sess->aux_data; - OscarData *od = gc->proto_data; +static int oscar_icon_req(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { + GaimConnection *gc = od->gc; va_list ap; guint16 type; guint8 flags = 0, length = 0; @@ -7905,15 +5438,15 @@ md5 = va_arg(ap, guchar *); if (flags == 0x41) { - if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_ICON) && !od->iconconnecting) { + if (!flap_connection_getbytype(od, SNAC_FAMILY_BART) && !od->iconconnecting) { od->iconconnecting = TRUE; od->set_icon = TRUE; - aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_ICON); + aim_reqservice(od, SNAC_FAMILY_BART); } else { struct stat st; char *iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(gaim_connection_get_account(gc))); if (iconfile == NULL) { - aim_ssi_delicon(od->sess); + aim_ssi_delicon(od); } else if (!g_stat(iconfile, &st)) { guchar *buf = g_malloc(st.st_size); FILE *file = g_fopen(iconfile, "rb"); @@ -7923,7 +5456,7 @@ fclose(file); gaim_debug_info("oscar", "Uploading icon to icon server\n"); - aim_bart_upload(od->sess, buf, st.st_size); + aim_bart_upload(od, buf, st.st_size); } else gaim_debug_error("oscar", "Can't open buddy icon file!\n"); @@ -7937,9 +5470,9 @@ } else if (flags == 0x81) { char *iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(gaim_connection_get_account(gc))); if (iconfile == NULL) - aim_ssi_delicon(od->sess); + aim_ssi_delicon(od); else { - aim_ssi_seticon(od->sess, md5, length); + aim_ssi_seticon(od, md5, length); g_free(iconfile); } } @@ -7958,25 +5491,25 @@ GaimAccount *account = gaim_connection_get_account(gc); OscarData *od = (OscarData *)gc->proto_data; - if (od->sess->ssi.received_data) { + if (od->ssi.received_data) { switch (account->perm_deny) { case GAIM_PRIVACY_ALLOW_ALL: - aim_ssi_setpermdeny(od->sess, 0x01, 0xffffffff); + aim_ssi_setpermdeny(od, 0x01, 0xffffffff); break; case GAIM_PRIVACY_ALLOW_BUDDYLIST: - aim_ssi_setpermdeny(od->sess, 0x05, 0xffffffff); + aim_ssi_setpermdeny(od, 0x05, 0xffffffff); break; case GAIM_PRIVACY_ALLOW_USERS: - aim_ssi_setpermdeny(od->sess, 0x03, 0xffffffff); + aim_ssi_setpermdeny(od, 0x03, 0xffffffff); break; case GAIM_PRIVACY_DENY_ALL: - aim_ssi_setpermdeny(od->sess, 0x02, 0xffffffff); + aim_ssi_setpermdeny(od, 0x02, 0xffffffff); break; case GAIM_PRIVACY_DENY_USERS: - aim_ssi_setpermdeny(od->sess, 0x04, 0xffffffff); + aim_ssi_setpermdeny(od, 0x04, 0xffffffff); break; default: - aim_ssi_setpermdeny(od->sess, 0x01, 0xffffffff); + aim_ssi_setpermdeny(od, 0x01, 0xffffffff); break; } } @@ -7985,29 +5518,29 @@ static void oscar_add_permit(GaimConnection *gc, const char *who) { OscarData *od = (OscarData *)gc->proto_data; gaim_debug_info("oscar", "ssi: About to add a permit\n"); - if (od->sess->ssi.received_data) - aim_ssi_addpermit(od->sess, who); + if (od->ssi.received_data) + aim_ssi_addpermit(od, who); } static void oscar_add_deny(GaimConnection *gc, const char *who) { OscarData *od = (OscarData *)gc->proto_data; gaim_debug_info("oscar", "ssi: About to add a deny\n"); - if (od->sess->ssi.received_data) - aim_ssi_adddeny(od->sess, who); + if (od->ssi.received_data) + aim_ssi_adddeny(od, who); } static void oscar_rem_permit(GaimConnection *gc, const char *who) { OscarData *od = (OscarData *)gc->proto_data; gaim_debug_info("oscar", "ssi: About to delete a permit\n"); - if (od->sess->ssi.received_data) - aim_ssi_delpermit(od->sess, who); + if (od->ssi.received_data) + aim_ssi_delpermit(od, who); } static void oscar_rem_deny(GaimConnection *gc, const char *who) { OscarData *od = (OscarData *)gc->proto_data; gaim_debug_info("oscar", "ssi: About to delete a deny\n"); - if (od->sess->ssi.received_data) - aim_ssi_deldeny(od->sess, who); + if (od->ssi.received_data) + aim_ssi_deldeny(od, who); } static GList * @@ -8088,7 +5621,7 @@ return; } - aim_ssi_editcomment(od->sess, g->name, data->name, text); + aim_ssi_editcomment(od, g->name, data->name, text); if (!aim_sncmp(data->name, gc->account->username)) gaim_check_comment(od, text); @@ -8117,7 +5650,7 @@ if (!(g = gaim_buddy_get_group(buddy))) return; - comment = aim_ssi_getcomment(od->sess->ssi.local, g->name, buddy->name); + comment = aim_ssi_getcomment(od->ssi.local, g->name, buddy->name); comment_utf8 = comment ? oscar_utf8_try_convert(gc->account, comment) : NULL; data->gc = gc; @@ -8132,10 +5665,58 @@ data); g_free(title); - free(comment); + g_free(comment); g_free(comment_utf8); } +static void +oscar_ask_directim_yes_cb(struct oscar_ask_directim_data *data) +{ + peer_connection_propose(data->od, OSCAR_CAPABILITY_DIRECTIM, data->who); + g_free(data->who); + g_free(data); +} + +static void +oscar_ask_directim_no_cb(struct oscar_ask_directim_data *data) +{ + g_free(data->who); + g_free(data); +} + +/* This is called from right-click menu on a buddy node. */ +static void +oscar_ask_directim(gpointer object, gpointer ignored) +{ + GaimBlistNode *node; + GaimBuddy *buddy; + GaimConnection *gc; + gchar *buf; + struct oscar_ask_directim_data *data; + + node = object; + + g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); + + buddy = (GaimBuddy *)node; + gc = gaim_account_get_connection(buddy->account); + + data = g_new0(struct oscar_ask_directim_data, 1); + data->who = g_strdup(buddy->name); + data->od = gc->proto_data; + buf = g_strdup_printf(_("You have selected to open a Direct IM connection with %s."), + buddy->name); + + gaim_request_action(gc, NULL, buf, + _("Because this reveals your IP address, it " + "may be considered a security risk. Do you " + "wish to continue?"), + 0, data, 2, + _("_Connect"), G_CALLBACK(oscar_ask_directim_yes_cb), + _("Cancel"), G_CALLBACK(oscar_ask_directim_no_cb)); + g_free(buf); +} + static GList *oscar_buddy_menu(GaimBuddy *buddy) { GaimConnection *gc = gaim_account_get_connection(buddy->account); @@ -8158,19 +5739,22 @@ #endif } else { aim_userinfo_t *userinfo; - userinfo = aim_locate_finduserinfo(od->sess, buddy->name); - - if (userinfo && aim_sncmp(gaim_account_get_username(buddy->account), buddy->name) && - GAIM_BUDDY_IS_ONLINE(buddy)) { - - if (userinfo->capabilities & AIM_CAPS_DIRECTIM) { + userinfo = aim_locate_finduserinfo(od, buddy->name); + + if (userinfo && + aim_sncmp(gaim_account_get_username(buddy->account), buddy->name) && + GAIM_BUDDY_IS_ONLINE(buddy)) + { + if (userinfo->capabilities & OSCAR_CAPABILITY_DIRECTIM) + { act = gaim_menu_action_new(_("Direct IM"), - GAIM_CALLBACK(oscar_ask_direct_im), + GAIM_CALLBACK(oscar_ask_directim), NULL, NULL); m = g_list_append(m, act); } #if 0 - if (userinfo->capabilities & AIM_CAPS_GETFILE) { + /* TODO: This menu item should be added by the core */ + if (userinfo->capabilities & OSCAR_CAPABILITY_GETFILE) { act = gaim_menu_action_new(_("Get File"), GAIM_CALLBACK(oscar_ask_getfile), NULL, NULL); @@ -8180,9 +5764,9 @@ } } - if (od->sess->ssi.received_data) { - char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, buddy->name); - if (gname && aim_ssi_waitingforauth(od->sess->ssi.local, gname, buddy->name)) { + if (od->ssi.received_data) { + char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, buddy->name); + if (gname && aim_ssi_waitingforauth(od->ssi.local, gname, buddy->name)) { act = gaim_menu_action_new(_("Re-request Authorization"), GAIM_CALLBACK(gaim_auth_sendrequest_menu), NULL, NULL); @@ -8220,7 +5804,7 @@ gaim_account_set_bool(account, "web_aware", web_aware); oscar_set_extendedstatus(gc); - aim_icq_setsecurity(od->sess, auth, web_aware); + aim_icq_setsecurity(od, auth, web_aware); } static void @@ -8257,12 +5841,12 @@ static void oscar_format_screenname(GaimConnection *gc, const char *nick) { OscarData *od = gc->proto_data; if (!aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), nick)) { - if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH)) { + if (!flap_connection_getbytype(od, SNAC_FAMILY_ADMIN)) { od->setnick = TRUE; od->newsn = g_strdup(nick); - aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH); + aim_reqservice(od, SNAC_FAMILY_ADMIN); } else { - aim_admin_setnick(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH), nick); + aim_admin_setnick(od, flap_connection_getbytype(od, SNAC_FAMILY_ADMIN), nick); } } else { gaim_notify_error(gc, NULL, _("The new formatting is invalid."), @@ -8282,15 +5866,19 @@ static void oscar_confirm_account(GaimPluginAction *action) { - GaimConnection *gc = (GaimConnection *) action->context; - OscarData *od = gc->proto_data; - OscarConnection *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH); - - if (conn) { - aim_admin_reqconfirm(od->sess, conn); + GaimConnection *gc; + OscarData *od; + FlapConnection *conn; + + gc = (GaimConnection *)action->context; + od = gc->proto_data; + + conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); + if (conn != NULL) { + aim_admin_reqconfirm(od, conn); } else { od->conf = TRUE; - aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH); + aim_reqservice(od, SNAC_FAMILY_ADMIN); } } @@ -8298,27 +5886,27 @@ { GaimConnection *gc = (GaimConnection *) action->context; OscarData *od = gc->proto_data; - OscarConnection *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH); + FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); if (conn) { - aim_admin_getinfo(od->sess, conn, 0x11); + aim_admin_getinfo(od, conn, 0x11); } else { od->reqemail = TRUE; - aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH); + aim_reqservice(od, SNAC_FAMILY_ADMIN); } } static void oscar_change_email(GaimConnection *gc, const char *email) { OscarData *od = gc->proto_data; - OscarConnection *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH); + FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); if (conn) { - aim_admin_setemail(od->sess, conn, email); + aim_admin_setemail(od, conn, email); } else { od->setemail = TRUE; od->email = g_strdup(email); - aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH); + aim_reqservice(od, SNAC_FAMILY_ADMIN); } } @@ -8353,7 +5941,7 @@ GaimBuddy *buddy = (GaimBuddy *)bnode; if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) continue; - if (buddy->account == gc->account && aim_ssi_waitingforauth(od->sess->ssi.local, group->name, buddy->name)) { + if (buddy->account == gc->account && aim_ssi_waitingforauth(od->ssi.local, group->name, buddy->name)) { if (gaim_buddy_get_alias_only(buddy)) nombre = g_strdup_printf(" %s (%s)", buddy->name, gaim_buddy_get_alias_only(buddy)); else @@ -8385,7 +5973,7 @@ { OscarData *od = (OscarData *)gc->proto_data; - aim_search_address(od->sess, od->conn, email); + aim_search_address(od, email); } static void oscar_show_find_email(GaimPluginAction *action) @@ -8422,7 +6010,7 @@ { GaimConnection *gc = (GaimConnection *) action->context; OscarData *od = gc->proto_data; - gchar *substituted = gaim_strreplace(od->sess->authinfo->chpassurl, "%s", gaim_account_get_username(gaim_connection_get_account(gc))); + gchar *substituted = gaim_strreplace(od->authinfo->chpassurl, "%s", gaim_account_get_username(gaim_connection_get_account(gc))); gaim_notify_uri(gc, substituted); g_free(substituted); } @@ -8436,12 +6024,11 @@ static void oscar_set_icon(GaimConnection *gc, const char *iconfile) { OscarData *od = gc->proto_data; - OscarSession *sess = od->sess; FILE *file; struct stat st; if (iconfile == NULL) { - aim_ssi_delicon(od->sess); + aim_ssi_delicon(od); } else if (!g_stat(iconfile, &st)) { guchar *buf = g_malloc(st.st_size); file = g_fopen(iconfile, "rb"); @@ -8462,18 +6049,95 @@ gaim_cipher_context_digest(context, 16, md5, NULL); gaim_cipher_context_destroy(context); - aim_ssi_seticon(sess, md5, 16); + aim_ssi_seticon(od, md5, 16); } else gaim_debug_error("oscar", "Can't open buddy icon file!\n"); g_free(buf); } else - gaim_debug_error("oscar", - "Can't stat buddy icon file!\n"); -} - - -static GList *oscar_actions(GaimPlugin *plugin, gpointer context) + gaim_debug_error("oscar", "Can't stat buddy icon file!\n"); +} + +/** + * Called by the Gaim core to determine whether or not we're + * allowed to send a file to this user. + */ +static gboolean +oscar_can_receive_file(GaimConnection *gc, const char *who) +{ + OscarData *od; + GaimAccount *account; + + od = gc->proto_data; + account = gaim_connection_get_account(gc); + + if (od != NULL) + { + aim_userinfo_t *userinfo; + userinfo = aim_locate_finduserinfo(od, who); + + /* + * Don't allowing sending a file to a user that does not support + * file transfer, and don't allow sending to ourselves. + */ + if ((userinfo != NULL) && + (userinfo->capabilities & OSCAR_CAPABILITY_SENDFILE) && + aim_sncmp(who, gaim_account_get_username(account))) + { + return TRUE; + } + } + + return FALSE; +} + +static GaimXfer * +oscar_new_xfer(GaimConnection *gc, const char *who) +{ + GaimXfer *xfer; + OscarData *od; + GaimAccount *account; + PeerConnection *conn; + + od = gc->proto_data; + account = gaim_connection_get_account(gc); + + xfer = gaim_xfer_new(account, GAIM_XFER_SEND, who); + gaim_xfer_ref(xfer); + gaim_xfer_set_init_fnc(xfer, peer_oft_sendcb_init); + gaim_xfer_set_cancel_send_fnc(xfer, peer_oft_cb_generic_cancel); + gaim_xfer_set_request_denied_fnc(xfer, peer_oft_cb_generic_cancel); + gaim_xfer_set_ack_fnc(xfer, peer_oft_sendcb_ack); + + conn = peer_connection_new(od, OSCAR_CAPABILITY_SENDFILE, who); + conn->flags |= PEER_CONNECTION_FLAG_INITIATED_BY_ME; + conn->flags |= PEER_CONNECTION_FLAG_APPROVED; + aim_icbm_makecookie(conn->cookie); + conn->xfer = xfer; + xfer->data = conn; + + return xfer; +} + +/* + * Called by the Gaim core when the user indicates that a + * file is to be sent to a special someone. + */ +static void +oscar_send_file(GaimConnection *gc, const char *who, const char *file) +{ + GaimXfer *xfer; + + xfer = oscar_new_xfer(gc, who); + + if (file != NULL) + gaim_xfer_request_accepted(xfer, file); + else + gaim_xfer_request(xfer); +} + +static GList * +oscar_actions(GaimPlugin *plugin, gpointer context) { GaimConnection *gc = (GaimConnection *) context; OscarData *od = gc->proto_data; @@ -8495,7 +6159,7 @@ oscar_change_pass); m = g_list_append(m, act); - if (od->sess->authinfo->chpassurl != NULL) + if (od->authinfo->chpassurl != NULL) { act = gaim_plugin_action_new(_("Change Password (URL)"), oscar_show_chpassurl); @@ -8526,11 +6190,11 @@ oscar_confirm_account); m = g_list_append(m, act); - act = gaim_plugin_action_new(_("Display Currently Registered Address"), + act = gaim_plugin_action_new(_("Display Currently Registered E-Mail Address"), oscar_show_email); m = g_list_append(m, act); - act = gaim_plugin_action_new(_("Change Currently Registered Address..."), + act = gaim_plugin_action_new(_("Change Currently Registered E-Mail Address..."), oscar_show_change_email); m = g_list_append(m, act); } @@ -8543,7 +6207,7 @@ m = g_list_append(m, NULL); - act = gaim_plugin_action_new(_("Search for Buddy by E-Mail..."), + act = gaim_plugin_action_new(_("Search for Buddy by E-Mail Address..."), oscar_show_find_email); m = g_list_append(m, act); @@ -8561,29 +6225,37 @@ OscarData *od = gc->proto_data; if (od->icq) { - aim_icq_changepasswd(od->sess, new); + aim_icq_changepasswd(od, new); } else { - OscarConnection *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH); + FlapConnection *conn; + conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); if (conn) { - aim_admin_changepasswd(od->sess, conn, new, old); + aim_admin_changepasswd(od, conn, new, old); } else { od->chpass = TRUE; od->oldp = g_strdup(old); od->newp = g_strdup(new); - aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH); + aim_reqservice(od, SNAC_FAMILY_ADMIN); } } } -static void oscar_convo_closed(GaimConnection *gc, const char *who) +static void +oscar_convo_closed(GaimConnection *gc, const char *who) { - OscarData *od = gc->proto_data; - struct oscar_direct_im *dim = oscar_direct_im_find(od, who); - - if (!dim) - return; - - oscar_direct_im_destroy(od, dim); + OscarData *od; + PeerConnection *conn; + + od = gc->proto_data; + conn = peer_connection_find_by_type(od, who, OSCAR_CAPABILITY_DIRECTIM); + + if (conn != NULL) + { + if (!conn->ready) + aim_im_sendch2_cancel(conn); + + peer_connection_destroy(conn, PEER_DISCONNECT_LOCAL_CLOSED); + } } static void @@ -8592,19 +6264,26 @@ { GaimConnection *gc = data; OscarData *od = gc->proto_data; - OscarSession *sess = od->sess; guint32 presence; - presence = aim_ssi_getpresence(sess->ssi.local); + presence = aim_ssi_getpresence(od->ssi.local); if (value) { presence &= ~AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES; - aim_ssi_setpresence(sess, presence); + aim_ssi_setpresence(od, presence); } else { presence |= AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES; - aim_ssi_setpresence(sess, presence); - } -} + aim_ssi_setpresence(od, presence); + } +} + +#ifdef USE_PRPL_PREFERENCES + ppref = gaim_plugin_pref_new_with_name_and_label("/plugins/prpl/oscar/recent_buddies", _("Use recent buddies group")); + gaim_plugin_pref_frame_add(frame, ppref); + + ppref = gaim_plugin_pref_new_with_name_and_label("/plugins/prpl/oscar/show_idle", _("Show how long you have been idle")); + gaim_plugin_pref_frame_add(frame, ppref); +#endif static const char * oscar_normalize(const GaimAccount *account, const char *str) @@ -8633,7 +6312,8 @@ return buf; } -static gboolean oscar_offline_message(const GaimBuddy *buddy) +static gboolean +oscar_offline_message(const GaimBuddy *buddy) { OscarData *od; GaimAccount *account; @@ -8756,8 +6436,9 @@ option = gaim_account_option_string_new(_("Encoding"), "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + /* TODO: Need to somehow invert this */ option = gaim_account_option_bool_new( - _("Use AIM/ICQ proxy server\n(slower, but usually works)"), "use_rv_proxy", + _("Always use AIM/ICQ proxy server\n(slower, but does not reveal your IP address)"), "use_rv_proxy", OSCAR_DEFAULT_USE_RV_PROXY); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); @@ -8765,7 +6446,6 @@ gaim_prefs_add_none("/plugins/prpl/oscar"); gaim_prefs_add_bool("/plugins/prpl/oscar/recent_buddies", FALSE); gaim_prefs_add_bool("/plugins/prpl/oscar/show_idle", FALSE); - gaim_prefs_remove("/plugins/prpl/oscar/use_rv_proxy"); }
--- a/src/protocols/oscar/oscar.h Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/oscar.h Fri Apr 07 05:10:56 2006 +0000 @@ -30,6 +30,7 @@ #define _OSCAR_H_ #include "debug.h" +#include "eventloop.h" #include "gaim_buffer.h" #include "internal.h" @@ -56,41 +57,19 @@ typedef struct _ClientInfo ClientInfo; typedef struct _FlapFrame FlapFrame; typedef struct _IcbmCookie IcbmCookie; -typedef struct _OscarConnection OscarConnection; -typedef struct _OscarSession OscarSession; +typedef struct _FlapConnection FlapConnection; +typedef struct _OscarData OscarData; +typedef struct _IcbmArgsCh2 IcbmArgsCh2; typedef guint32 aim_snacid_t; typedef guint16 flap_seqnum_t; -#include "peer.h" #include "snactypes.h" #ifdef __cplusplus extern "C" { #endif -#define WIN32_STATIC -#if defined(_WIN32) && !defined(WIN32_STATIC) -/* - * For a win32 DLL, we define WIN32_INDLL if this file - * is included while compiling the DLL. If it's not - * defined (it's included in a client app), the symbols - * will be imported instead of exported. - */ -#ifdef WIN32_INDLL -#define faim_export __declspec(dllexport) -#else -#define faim_export __declspec(dllimport) -#endif /* WIN32_INDLL */ -#define faim_internal -#else -/* - * Nothing normally needed for unix... - */ -#define faim_export -#define faim_internal -#endif - #define FAIM_SNAC_HASH_SIZE 16 /* @@ -113,7 +92,7 @@ * send any more than 1kb. Amaze all your windows friends * with utterly oversized instant messages! * - * XXX: the real limit is the total SNAC size at 8192. Fix this. + * TODO: the real limit is the total SNAC size at 8192. Fix this. * */ #define MAXMSGLEN 7987 @@ -306,103 +285,38 @@ #define CLIENTINFO_AIM_KNOWNGOOD CLIENTINFO_AIM_5_1_3036 #define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQ_5_45_3777 -/* - * These could be arbitrary, but its easier to use the actual AIM values - */ -#define AIM_CONN_TYPE_BOS 0x0002 -#define AIM_CONN_TYPE_ADS 0x0005 -#define AIM_CONN_TYPE_AUTH 0x0007 -#define AIM_CONN_TYPE_CHATNAV 0x000d -#define AIM_CONN_TYPE_CHAT 0x000e -#define AIM_CONN_TYPE_SEARCH 0x000f -#define AIM_CONN_TYPE_ICON 0x0010 -#define AIM_CONN_TYPE_EMAIL 0x0018 - -/* they start getting arbitrary for rendezvous stuff =) */ -#define AIM_CONN_TYPE_RENDEZVOUS_PROXY 0xfffd /* these speak a strange language */ -#define AIM_CONN_TYPE_RENDEZVOUS 0xfffe /* these do not speak FLAP! */ -#define AIM_CONN_TYPE_LISTENER 0xffff /* socket waiting for accept() */ - -/* Command types for doing a rendezvous proxy login - * Thanks to Keith Lea and the Joust project for documenting these commands well */ -#define AIM_RV_PROXY_PACKETVER_DFLT 0x044a -#define AIM_RV_PROXY_ERROR 0x0001 -#define AIM_RV_PROXY_INIT_SEND 0x0002 /* First command sent when creating a connection */ -#define AIM_RV_PROXY_INIT_RECV 0x0004 /* First command sent when receiving existing connection */ -#define AIM_RV_PROXY_ACK 0x0003 -#define AIM_RV_PROXY_READY 0x0005 - -/* Number of bytes expected in each of the above packets, including the 2 bytes specifying length */ -#define AIM_RV_PROXY_ERROR_LEN 14 -#define AIM_RV_PROXY_INIT_SEND_LEN 55 -#define AIM_RV_PROXY_INIT_RECV_LEN 57 -#define AIM_RV_PROXY_ACK_LEN 18 -#define AIM_RV_PROXY_READY_LEN 12 -#define AIM_RV_PROXY_HDR_LEN 12 /* Bytes in just the header alone */ - -/* Default values for unknown/unused values in rendezvous proxy negotiation packets */ -#define AIM_RV_PROXY_SERVER_FLAGS 0x0220 /* Default flags sent by proxy server */ -#define AIM_RV_PROXY_CLIENT_FLAGS 0x0000 /* Default flags sent by client */ -#define AIM_RV_PROXY_UNKNOWNA_DFLT 0x00000000 /* Default value for an unknown block */ -#define AIM_RV_PROXY_SERVER_URL "ars.oscar.aol.com" -#define AIM_RV_PROXY_CONNECT_PORT 5190 /* The port we should always connect to */ - -/* What is the purpose of this transfer? (Who will end up with a new file?) - * These values are used in peer_connection->send_or_recv */ -#define AIM_XFER_SEND 0x0001 -#define AIM_XFER_RECV 0x0002 - -/* Via what method is the data getting routed? - * These values are used in peer_connection->method */ -#define AIM_XFER_DIRECT 0x0001 /* Direct connection; receiver connects to sender */ -#define AIM_XFER_REDIR 0x0002 /* Redirected connection; sender connects to receiver */ -#define AIM_XFER_PROXY 0x0003 /* Proxied connection */ - -/* Who requested the proxy? - * The difference between a stage 2 and stage 3 proxied transfer is that the receiver does the - * initial login for a stage 2, but the sender must do it for a stage 3. - * These values are used in peer_connection->stage */ -#define AIM_XFER_PROXY_NONE 0x0001 -#define AIM_XFER_PROXY_STG1 0x0002 /* Sender requested a proxy be used (stage1) */ -#define AIM_XFER_PROXY_STG2 0x0003 /* Receiver requested a proxy be used (stage2) */ -#define AIM_XFER_PROXY_STG3 0x0004 /* Receiver requested a proxy be used (stage3) */ - -/* - * Subtypes, we need these for OFT stuff. - */ -#define AIM_CONN_SUBTYPE_OFT_DIRECTIM 0x0001 -#define AIM_CONN_SUBTYPE_OFT_GETFILE 0x0002 -#define AIM_CONN_SUBTYPE_OFT_SENDFILE 0x0003 -#define AIM_CONN_SUBTYPE_OFT_BUDDYICON 0x0004 -#define AIM_CONN_SUBTYPE_OFT_VOICE 0x0005 - -/* - * Status values returned from aim_conn_new(). ORed together. - */ -#define AIM_CONN_STATUS_READY 0x0001 -#define AIM_CONN_STATUS_INTERNALERR 0x0002 -#define AIM_CONN_STATUS_RESOLVERR 0x0040 -#define AIM_CONN_STATUS_CONNERR 0x0080 -#define AIM_CONN_STATUS_INPROGRESS 0x0100 - -#define AIM_FRAMETYPE_FLAP 0x0000 -#define AIM_FRAMETYPE_OFT 0x0001 - -struct _OscarConnection +typedef enum { - int fd; - GaimCircBuffer *buffer_outgoing; - guint16 type; - guint16 subtype; - flap_seqnum_t seqnum; - guint32 status; - void *internal; /* internal conn-specific libfaim data */ - time_t lastactivity; /* time of last transmit */ - void *handlerlist; - OscarSession *sessv; /* pointer to parent session */ - void *inside; /* only accessible from inside libfaim */ - struct _OscarConnection *next; -}; + OSCAR_CAPABILITY_BUDDYICON = 0x00000001, + OSCAR_CAPABILITY_TALK = 0x00000002, + OSCAR_CAPABILITY_DIRECTIM = 0x00000004, + OSCAR_CAPABILITY_CHAT = 0x00000008, + OSCAR_CAPABILITY_GETFILE = 0x00000010, + OSCAR_CAPABILITY_SENDFILE = 0x00000020, + OSCAR_CAPABILITY_GAMES = 0x00000040, + OSCAR_CAPABILITY_ADDINS = 0x00000080, + OSCAR_CAPABILITY_SENDBUDDYLIST = 0x00000100, + OSCAR_CAPABILITY_GAMES2 = 0x00000200, + OSCAR_CAPABILITY_ICQ_DIRECT = 0x00000400, + OSCAR_CAPABILITY_APINFO = 0x00000800, + OSCAR_CAPABILITY_ICQRTF = 0x00001000, + OSCAR_CAPABILITY_EMPTY = 0x00002000, + OSCAR_CAPABILITY_ICQSERVERRELAY = 0x00004000, + OSCAR_CAPABILITY_ICQUTF8OLD = 0x00008000, + OSCAR_CAPABILITY_TRILLIANCRYPT = 0x00010000, + OSCAR_CAPABILITY_ICQUTF8 = 0x00020000, + OSCAR_CAPABILITY_INTEROPERATE = 0x00040000, + OSCAR_CAPABILITY_ICHAT = 0x00080000, + OSCAR_CAPABILITY_HIPTOP = 0x00100000, + OSCAR_CAPABILITY_SECUREIM = 0x00200000, + OSCAR_CAPABILITY_SMS = 0x00400000, + OSCAR_CAPABILITY_GENERICUNKNOWN = 0x00800000, + OSCAR_CAPABILITY_VIDEO = 0x01000000, + OSCAR_CAPABILITY_ICHATAV = 0x02000000, + OSCAR_CAPABILITY_LIVEVIDEO = 0x04000000, + OSCAR_CAPABILITY_CAMERA = 0x08000000, + OSCAR_CAPABILITY_LAST = 0x10000000 +} OscarCapability; /* * Byte Stream type. Sort of. @@ -427,22 +341,30 @@ struct _FlapFrame { - guint8 hdrtype; /* defines which piece of the union to use */ - union { - struct { - guint8 channel; - flap_seqnum_t seqnum; - } flap; - struct { - guint8 magic[4]; /* ODC2 or OFT2 */ - guint16 hdrlen; - guint16 type; - } rend; - } hdr; - ByteStream data; /* payload stream */ - OscarConnection *conn; /* the connection it came in on/is going out on */ - guint8 handled; /* 0 = new, !0 = been handled */ - struct _FlapFrame *next; + guint8 channel; + flap_seqnum_t seqnum; + ByteStream data; /* payload stream */ +}; + +struct _FlapConnection +{ + OscarData *od; /**< Pointer to parent session. */ + int fd; + time_t lastactivity; /**< Time of last transmit. */ + gboolean connected; + guint destroy_timeout; + + FlapFrame buffer_incoming; + GaimCircBuffer *buffer_outgoing; + guint watcher_incoming; + guint watcher_outgoing; + + guint16 type; + guint16 subtype; + flap_seqnum_t seqnum; + guint32 status; + void *internal; /* internal conn-specific libfaim data */ + void *inside; /* only accessible from inside libfaim */ }; struct _IcbmCookie @@ -454,67 +376,76 @@ struct _IcbmCookie *next; }; +#include "peer.h" + /* * AIM Session: The main client-data interface. * */ -struct _OscarSession +struct _OscarData { + gboolean iconconnecting; + gboolean set_icon; + + GSList *create_rooms; + + gboolean conf; + gboolean reqemail; + gboolean setemail; + char *email; + gboolean setnick; + char *newsn; + gboolean chpass; + char *oldp; + char *newp; + + GSList *oscar_chats; + GHashTable *buddyinfo; + GSList *requesticon; + + gboolean killme; + gboolean icq; + guint icontimer; + guint getblisttimer; + guint getinfotimer; + gint timeoffset; + + struct { + guint maxwatchers; /* max users who can watch you */ + guint maxbuddies; /* max users you can watch */ + guint maxgroups; /* max groups in server list */ + guint maxpermits; /* max users on permit list */ + guint maxdenies; /* max users on deny list */ + guint maxsiglen; /* max size (bytes) of profile */ + guint maxawaymsglen; /* max size (bytes) of posted away message */ + } rights; /* ---- Client Accessible ------------------------ */ /* Our screen name. */ + /* TODO: Get rid of this and use gaim_account_get_username() everywhere? */ char sn[MAXSNLEN+1]; - /* - * Pointer to anything the client wants to - * explicitly associate with this session. - * - * This is for use in the callbacks mainly. In any - * callback, you can access this with sess->aux_data. - * - */ - void *aux_data; + GaimConnection *gc; /* ---- Internal Use Only ------------------------ */ - /* - * Transmit/receive queues. - * - * These are only used when you don't use your own lowlevel - * I/O. I don't suggest that you use libfaim's internal I/O. - * Its really bad and the API/event model is quirky at best. - * - */ - FlapFrame *queue_outgoing; - FlapFrame *queue_incoming; - - /* - * Tx Enqueuing function. - * - * This is how you override the transmit direction of libfaim's - * internal I/O. This function will be called whenever it needs - * to send something. - * - */ - int (*tx_enqueue)(OscarSession *, FlapFrame *); - void *modlistv; - struct { - char server[128]; - char username[128]; - char password[128]; - } socksproxy; - /* * Outstanding snac handling * - * XXX: Should these be per-connection? -mid + * TODO: Should these be per-connection? -mid */ void *snac_hash[FAIM_SNAC_HASH_SIZE]; aim_snacid_t snacid_next; + /* + * TODO: Data specific to a certain family should go into a + * hashtable and the core parts of libfaim shouldn't + * need to know about them. + */ + IcbmCookie *msgcookies; struct aim_icq_info *icq_info; struct aim_authresp_info *authinfo; @@ -538,7 +469,10 @@ int waiting_for_ack; } ssi; - /** A linked list containing OscarConnections. */ + /* TODO: Implement this as a HashTable for HUGE speed improvement! */ + GList *handlerlist; + + /** A linked list containing FlapConnections. */ GList *oscar_connections; /** A linked list containing PeerConnections. */ @@ -546,40 +480,22 @@ }; /* Valid for calling aim_icq_setstatus() and for aim_userinfo_t->icqinfo.status */ -#define AIM_ICQ_STATE_NORMAL 0x00000000 -#define AIM_ICQ_STATE_AWAY 0x00000001 -#define AIM_ICQ_STATE_DND 0x00000002 -#define AIM_ICQ_STATE_OUT 0x00000004 -#define AIM_ICQ_STATE_BUSY 0x00000010 -#define AIM_ICQ_STATE_CHAT 0x00000020 -#define AIM_ICQ_STATE_INVISIBLE 0x00000100 -#define AIM_ICQ_STATE_WEBAWARE 0x00010000 -#define AIM_ICQ_STATE_HIDEIP 0x00020000 -#define AIM_ICQ_STATE_BIRTHDAY 0x00080000 -#define AIM_ICQ_STATE_DIRECTDISABLED 0x00100000 -#define AIM_ICQ_STATE_ICQHOMEPAGE 0x00200000 -#define AIM_ICQ_STATE_DIRECTREQUIREAUTH 0x10000000 -#define AIM_ICQ_STATE_DIRECTCONTACTLIST 0x20000000 +#define AIM_ICQ_STATE_NORMAL 0x00000000 +#define AIM_ICQ_STATE_AWAY 0x00000001 +#define AIM_ICQ_STATE_DND 0x00000002 +#define AIM_ICQ_STATE_OUT 0x00000004 +#define AIM_ICQ_STATE_BUSY 0x00000010 +#define AIM_ICQ_STATE_CHAT 0x00000020 +#define AIM_ICQ_STATE_INVISIBLE 0x00000100 +#define AIM_ICQ_STATE_WEBAWARE 0x00010000 +#define AIM_ICQ_STATE_HIDEIP 0x00020000 +#define AIM_ICQ_STATE_BIRTHDAY 0x00080000 +#define AIM_ICQ_STATE_DIRECTDISABLED 0x00100000 +#define AIM_ICQ_STATE_ICQHOMEPAGE 0x00200000 +#define AIM_ICQ_STATE_DIRECTREQUIREAUTH 0x10000000 +#define AIM_ICQ_STATE_DIRECTCONTACTLIST 0x20000000 -/* - * Get command from connections - * - * aim_get_commmand() is the libfaim lowlevel I/O in the receive direction. - * XXX Make this easily overridable. - * - */ -faim_export int aim_get_command(OscarSession *, OscarConnection *); - -/* - * Dispatch commands that are in the rx queue. - */ -faim_export void aim_rxdispatch(OscarSession *); - -faim_export int aim_debugconn_sendconnect(OscarSession *sess, OscarConnection *conn); - -void oscar_connection_destroy(OscarSession *sess, OscarConnection *deadconn); - -typedef int (*aim_rxcallback_t)(OscarSession *, FlapFrame *, ...); +typedef int (*aim_rxcallback_t)(OscarData *od, FlapConnection *conn, FlapFrame *frame, ...); /* family_auth.c */ @@ -613,50 +529,47 @@ const char *ip; guint16 cookielen; const guint8 *cookie; - struct { /* group == AIM_CONN_TYPE_CHAT */ + struct { /* group == SNAC_FAMILY_CHAT */ guint16 exchange; const char *room; guint16 instance; } chat; }; -faim_export int aim_clientready(OscarSession *sess, OscarConnection *conn); -faim_export int aim_sendflapver(OscarSession *sess, OscarConnection *conn); -faim_export int aim_request_login(OscarSession *sess, OscarConnection *conn, const char *sn); -faim_export int aim_send_login(OscarSession *, OscarConnection *, const char *, const char *, ClientInfo *, const char *key); -/* 0x000b */ faim_export int aim_auth_securid_send(OscarSession *sess, const char *securid); +int aim_clientready(OscarData *od, FlapConnection *conn); +int aim_request_login(OscarData *od, FlapConnection *conn, const char *sn); +int aim_send_login(OscarData *, FlapConnection *, const char *, const char *, ClientInfo *, const char *key); +/* 0x000b */ int aim_auth_securid_send(OscarData *od, const char *securid); -faim_export void aim_purge_rxqueue(OscarSession *); -faim_export void aim_cleansnacs(OscarSession *, int maxage); +void aim_cleansnacs(OscarData *, int maxage); -#define AIM_TX_QUEUED 0 /* default */ -#define AIM_TX_IMMEDIATE 1 -faim_export int aim_tx_setenqueue(OscarSession *sess, int what, int (*func)(OscarSession *, FlapFrame *)); - -faim_export int aim_tx_flushqueue(OscarSession *); +int oscar_data_addhandler(OscarData *od, guint16 family, guint16 type, aim_rxcallback_t newhandler, guint16 flags); +void aim_clearhandlers(OscarData *od); -faim_export int aim_conn_addhandler(OscarSession *, OscarConnection *conn, guint16 family, guint16 type, aim_rxcallback_t newhandler, guint16 flags); -faim_export int aim_clearhandlers(OscarConnection *conn); +/* flap_connection.c */ +FlapConnection *flap_connection_new(OscarData *, int type); +void flap_connection_addgroup(FlapConnection *conn, guint16 group); +void flap_connection_close(OscarData *od, FlapConnection *conn); +void flap_connection_destroy(FlapConnection *conn); +void flap_connection_schedule_destroy(FlapConnection *conn); +FlapConnection *flap_connection_findbygroup(OscarData *od, guint16 group); +FlapConnection *flap_connection_getbytype(OscarData *, int type); +FlapConnection *flap_connection_getbytype_all(OscarData *, int type); +void flap_connection_recv_cb(gpointer data, gint source, GaimInputCondition cond); +FlapConnection *flap_connection_clone(OscarData *od, FlapConnection *src); +void flap_connection_send(FlapConnection *conn, FlapFrame *frame); +void flap_connection_send_version(OscarData *od, FlapConnection *conn); +void flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy); +void flap_connection_send_keepalive(OscarData *od, FlapConnection *conn); +FlapFrame *flap_frame_new(OscarData *od, guint16 channel, int datalen); -faim_export OscarConnection *aim_conn_findbygroup(OscarSession *sess, guint16 group); -faim_export OscarSession *aim_conn_getsess(OscarConnection *conn); -void oscar_connection_destroy(OscarSession *sess, OscarConnection *conn); -faim_export void aim_conn_close(OscarSession *sess, OscarConnection *conn); -faim_export OscarConnection *oscar_connection_new(OscarSession *, int type); -faim_export int aim_conn_isready(OscarConnection *); -faim_export int aim_conn_setstatus(OscarConnection *, int); -faim_export int aim_conn_completeconnect(OscarSession *sess, OscarConnection *conn); -faim_export int aim_conn_isconnecting(OscarConnection *conn); -OscarSession *oscar_session_new(void); -void oscar_session_destroy(OscarSession *); - -faim_export OscarConnection *aim_getconn_type(OscarSession *, int type); -faim_export OscarConnection *aim_getconn_type_all(OscarSession *, int type); +OscarData *oscar_data_new(void); +void oscar_data_destroy(OscarData *); /* 0x0001 - family_oservice.c */ -faim_export int aim_srv_setstatusmsg(OscarSession *sess, const char *msg); -faim_export int aim_srv_setidle(OscarSession *sess, guint32 idletime); +int aim_srv_setstatusmsg(OscarData *od, const char *msg); +int aim_srv_setidle(OscarData *od, guint32 idletime); /* misc.c */ @@ -670,29 +583,28 @@ #define AIM_WARN_ANON 0x01 -faim_export int aim_sendpauseack(OscarSession *sess, OscarConnection *conn); -faim_export int aim_nop(OscarSession *, OscarConnection *); -faim_export int aim_flap_nop(OscarSession *sess, OscarConnection *conn); -faim_export int aim_bos_changevisibility(OscarSession *, OscarConnection *, int, const char *); -faim_export int aim_bos_setgroupperm(OscarSession *, OscarConnection *, guint32 mask); -faim_export int aim_bos_setprivacyflags(OscarSession *, OscarConnection *, guint32); -faim_export int aim_reqpersonalinfo(OscarSession *, OscarConnection *); -faim_export int aim_reqservice(OscarSession *, OscarConnection *, guint16); -faim_export int aim_bos_reqrights(OscarSession *, OscarConnection *); -faim_export int aim_setextstatus(OscarSession *sess, guint32 status); +int aim_sendpauseack(OscarData *od, FlapConnection *conn); +int aim_nop(OscarData *, FlapConnection *); +int aim_bos_changevisibility(OscarData *, FlapConnection *, int, const char *); +int aim_bos_setgroupperm(OscarData *, FlapConnection *, guint32 mask); +int aim_bos_setprivacyflags(OscarData *, FlapConnection *, guint32); +int aim_reqpersonalinfo(OscarData *, FlapConnection *); +int aim_reqservice(OscarData *, guint16); +int aim_bos_reqrights(OscarData *, FlapConnection *); +int aim_setextstatus(OscarData *od, guint32 status); #define AIM_CLIENTTYPE_UNKNOWN 0x0000 #define AIM_CLIENTTYPE_MC 0x0001 #define AIM_CLIENTTYPE_WINAIM 0x0002 #define AIM_CLIENTTYPE_WINAIM41 0x0003 #define AIM_CLIENTTYPE_AOL_TOC 0x0004 -faim_export guint16 aim_im_fingerprint(const guint8 *msghdr, int len); +guint16 aim_im_fingerprint(const guint8 *msghdr, int len); #define AIM_RATE_CODE_CHANGE 0x0001 #define AIM_RATE_CODE_WARNING 0x0002 #define AIM_RATE_CODE_LIMIT 0x0003 #define AIM_RATE_CODE_CLEARLIMIT 0x0004 -faim_export int aim_ads_requestads(OscarSession *sess, OscarConnection *conn); +int aim_ads_requestads(OscarData *od, FlapConnection *conn); @@ -778,11 +690,11 @@ aim_mpmsg_section_t *parts; } aim_mpmsg_t; -faim_export int aim_mpmsg_init(OscarSession *sess, aim_mpmsg_t *mpm); -faim_export int aim_mpmsg_addraw(OscarSession *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const gchar *data, guint16 datalen); -faim_export int aim_mpmsg_addascii(OscarSession *sess, aim_mpmsg_t *mpm, const char *ascii); -faim_export int aim_mpmsg_addunicode(OscarSession *sess, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen); -faim_export void aim_mpmsg_free(OscarSession *sess, aim_mpmsg_t *mpm); +int aim_mpmsg_init(OscarData *od, aim_mpmsg_t *mpm); +int aim_mpmsg_addraw(OscarData *od, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const gchar *data, guint16 datalen); +int aim_mpmsg_addascii(OscarData *od, aim_mpmsg_t *mpm, const char *ascii); +int aim_mpmsg_addunicode(OscarData *od, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen); +void aim_mpmsg_free(OscarData *od, aim_mpmsg_t *mpm); /* * Arguments to aim_send_im_ext(). @@ -872,24 +784,26 @@ }; /* Valid values for channel 2 args->status */ -#define AIM_RENDEZVOUS_PROPOSE 0x0000 -#define AIM_RENDEZVOUS_CANCEL 0x0001 -#define AIM_RENDEZVOUS_ACCEPT 0x0002 +#define AIM_RENDEZVOUS_PROPOSE 0x0000 +#define AIM_RENDEZVOUS_CANCEL 0x0001 +#define AIM_RENDEZVOUS_CONNECTED 0x0002 -struct aim_incomingim_ch2_args +struct _IcbmArgsCh2 { guint16 status; guchar cookie[8]; - int reqclass; + int type; /* One of the OSCAR_CAPABILITY_ constants */ const char *proxyip; const char *clientip; const char *verifiedip; guint16 port; + gboolean use_proxy; guint16 errorcode; const char *msg; /* invite message or file description */ guint16 msglen; const char *encoding; const char *language; + guint16 requestnumber; union { struct { guint32 checksum; @@ -911,9 +825,6 @@ guint16 totfiles; guint32 totsize; char *filename; - /* reqnum: 0x0001 usually; 0x0002 = reply request for stage 2 proxy transfer */ - guint16 reqnum; - guint8 use_proxy; /* Did the user request that we use a rv proxy? */ } sendfile; } info; void *destructor; /* used internally only */ @@ -934,43 +845,49 @@ }; /* SNAC sending functions */ -/* 0x0002 */ faim_export int aim_im_setparams(OscarSession *sess, struct aim_icbmparameters *params); -/* 0x0004 */ faim_export int aim_im_reqparams(OscarSession *sess); -/* 0x0006 */ faim_export int aim_im_sendch1_ext(OscarSession *sess, struct aim_sendimext_args *args); -/* 0x0006 */ faim_export int aim_im_sendch1(OscarSession *, const char *destsn, guint16 flags, const char *msg); -/* 0x0006 */ faim_export int aim_im_sendch2_chatinvite(OscarSession *sess, const char *sn, const char *msg, guint16 exchange, const char *roomname, guint16 instance); -/* 0x0006 */ faim_export int aim_im_sendch2_icon(OscarSession *sess, const char *sn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum); -/* 0x0006 */ faim_export int aim_im_sendch2_rtfmsg(OscarSession *sess, struct aim_sendrtfmsg_args *args); -/* 0x0006 */ faim_export int aim_im_sendch2_odcrequest(OscarSession *sess, guchar *cookie, gboolean usecookie, const char *sn, const guint8 *ip, guint16 port); -/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_ask(OscarSession *sess, PeerConnection *peer_connection); -/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_accept(OscarSession *sess, PeerConnection *info); -/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_cancel(OscarSession *sess, PeerConnection *peer_connection); -/* 0x0006 */ faim_export int aim_im_sendch2_geticqaway(OscarSession *sess, const char *sn, int type); -/* 0x0006 */ faim_export int aim_im_sendch4(OscarSession *sess, const char *sn, guint16 type, const char *message); -/* 0x0008 */ faim_export int aim_im_warn(OscarSession *sess, OscarConnection *conn, const char *destsn, guint32 flags); -/* 0x000b */ faim_export int aim_im_denytransfer(OscarSession *sess, const char *sender, const guchar *cookie, guint16 code); -/* 0x0014 */ faim_export int aim_im_sendmtn(OscarSession *sess, guint16 type1, const char *sn, guint16 type2); -faim_export void aim_icbm_makecookie(guchar* cookie); +/* 0x0002 */ int aim_im_setparams(OscarData *od, struct aim_icbmparameters *params); +/* 0x0004 */ int aim_im_reqparams(OscarData *od); +/* 0x0006 */ int aim_im_sendch1_ext(OscarData *od, struct aim_sendimext_args *args); +/* 0x0006 */ int aim_im_sendch1(OscarData *, const char *destsn, guint16 flags, const char *msg); +/* 0x0006 */ int aim_im_sendch2_chatinvite(OscarData *od, const char *sn, const char *msg, guint16 exchange, const char *roomname, guint16 instance); +/* 0x0006 */ int aim_im_sendch2_icon(OscarData *od, const char *sn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum); +/* 0x0006 */ int aim_im_sendch2_rtfmsg(OscarData *od, struct aim_sendrtfmsg_args *args); + +/* 0x0006 */ void aim_im_sendch2_cancel(PeerConnection *peer_conn); +/* 0x0006 */ void aim_im_sendch2_connected(PeerConnection *peer_conn); +/* 0x0006 */ void aim_im_sendch2_odc_requestdirect(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 port, guint16 requestnumber); +/* 0x0006 */ void aim_im_sendch2_odc_requestproxy(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 pin, guint16 requestnumber); +/* 0x0006 */ void aim_im_sendch2_sendfile_requestdirect(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 port, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles); +/* 0x0006 */ void aim_im_sendch2_sendfile_requestproxy(OscarData *od, guchar *cookie, const char *sn, const guint8 *ip, guint16 pin, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles); + +/* 0x0006 */ int aim_im_sendch2_geticqaway(OscarData *od, const char *sn, int type); +/* 0x0006 */ int aim_im_sendch4(OscarData *od, const char *sn, guint16 type, const char *message); +/* 0x0008 */ int aim_im_warn(OscarData *od, FlapConnection *conn, const char *destsn, guint32 flags); +/* 0x000b */ int aim_im_denytransfer(OscarData *od, const char *sn, const guchar *cookie, guint16 code); +/* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *sn, guint16 type2); +void aim_icbm_makecookie(guchar* cookie); +gchar *oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen); +gchar *gaim_plugin_oscar_decode_im_part(GaimAccount *account, const char *sourcesn, guint16 charset, guint16 charsubset, const gchar *data, gsize datalen); /* 0x0002 - family_locate.c */ /* * AIM User Info, Standard Form. */ -#define AIM_FLAG_UNCONFIRMED 0x0001 /* "damned transients" */ -#define AIM_FLAG_ADMINISTRATOR 0x0002 -#define AIM_FLAG_AOL 0x0004 -#define AIM_FLAG_OSCAR_PAY 0x0008 -#define AIM_FLAG_FREE 0x0010 -#define AIM_FLAG_AWAY 0x0020 -#define AIM_FLAG_ICQ 0x0040 -#define AIM_FLAG_WIRELESS 0x0080 -#define AIM_FLAG_UNKNOWN100 0x0100 -#define AIM_FLAG_UNKNOWN200 0x0200 -#define AIM_FLAG_ACTIVEBUDDY 0x0400 -#define AIM_FLAG_UNKNOWN800 0x0800 -#define AIM_FLAG_ABINTERNAL 0x1000 -#define AIM_FLAG_ALLUSERS 0x001f +#define AIM_FLAG_UNCONFIRMED 0x0001 /* "damned transients" */ +#define AIM_FLAG_ADMINISTRATOR 0x0002 +#define AIM_FLAG_AOL 0x0004 +#define AIM_FLAG_OSCAR_PAY 0x0008 +#define AIM_FLAG_FREE 0x0010 +#define AIM_FLAG_AWAY 0x0020 +#define AIM_FLAG_ICQ 0x0040 +#define AIM_FLAG_WIRELESS 0x0080 +#define AIM_FLAG_UNKNOWN100 0x0100 +#define AIM_FLAG_UNKNOWN200 0x0200 +#define AIM_FLAG_ACTIVEBUDDY 0x0400 +#define AIM_FLAG_UNKNOWN800 0x0800 +#define AIM_FLAG_ABINTERNAL 0x1000 +#define AIM_FLAG_ALLUSERS 0x001f #define AIM_USERINFO_PRESENT_FLAGS 0x00000001 #define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002 @@ -1026,40 +943,10 @@ struct aim_userinfo_s *next; } aim_userinfo_t; -#define AIM_CAPS_BUDDYICON 0x00000001 -#define AIM_CAPS_TALK 0x00000002 -#define AIM_CAPS_DIRECTIM 0x00000004 -#define AIM_CAPS_CHAT 0x00000008 -#define AIM_CAPS_GETFILE 0x00000010 -#define AIM_CAPS_SENDFILE 0x00000020 -#define AIM_CAPS_GAMES 0x00000040 -#define AIM_CAPS_ADDINS 0x00000080 -#define AIM_CAPS_SENDBUDDYLIST 0x00000100 -#define AIM_CAPS_GAMES2 0x00000200 -#define AIM_CAPS_ICQ_DIRECT 0x00000400 -#define AIM_CAPS_APINFO 0x00000800 -#define AIM_CAPS_ICQRTF 0x00001000 -#define AIM_CAPS_EMPTY 0x00002000 -#define AIM_CAPS_ICQSERVERRELAY 0x00004000 -#define AIM_CAPS_ICQUTF8OLD 0x00008000 -#define AIM_CAPS_TRILLIANCRYPT 0x00010000 -#define AIM_CAPS_ICQUTF8 0x00020000 -#define AIM_CAPS_INTEROPERATE 0x00040000 -#define AIM_CAPS_ICHAT 0x00080000 -#define AIM_CAPS_HIPTOP 0x00100000 -#define AIM_CAPS_SECUREIM 0x00200000 -#define AIM_CAPS_SMS 0x00400000 -#define AIM_CAPS_GENERICUNKNOWN 0x00800000 -#define AIM_CAPS_VIDEO 0x01000000 -#define AIM_CAPS_ICHATAV 0x02000000 -#define AIM_CAPS_LIVEVIDEO 0x04000000 -#define AIM_CAPS_CAMERA 0x08000000 -#define AIM_CAPS_LAST 0x10000000 - #define AIM_SENDMEMBLOCK_FLAG_ISREQUEST 0 #define AIM_SENDMEMBLOCK_FLAG_ISHASH 1 -faim_export int aim_sendmemblock(OscarSession *sess, OscarConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag); +int aim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag); struct aim_invite_priv { @@ -1086,32 +973,37 @@ #define AIM_COOKIETYPE_OFTIMAGE 0x14 #define AIM_COOKIETYPE_OFTICON 0x15 -faim_export aim_userinfo_t *aim_locate_finduserinfo(OscarSession *sess, const char *sn); -faim_export void aim_locate_dorequest(OscarSession *sess); +aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *sn); +void aim_locate_dorequest(OscarData *od); -/* 0x0002 */ faim_export int aim_locate_reqrights(OscarSession *sess); -/* 0x0004 */ faim_export int aim_locate_setcaps(OscarSession *sess, guint32 caps); -/* 0x0004 */ faim_export int aim_locate_setprofile(OscarSession *sess, const char *profile_encoding, const gchar *profile, const int profile_len, const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len); -/* 0x0005 */ faim_export int aim_locate_getinfo(OscarSession *sess, const char *, guint16); -/* 0x0009 */ faim_export int aim_locate_setdirinfo(OscarSession *sess, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy); -/* 0x000b */ faim_export int aim_locate_000b(OscarSession *sess, const char *sn); -/* 0x000f */ faim_export int aim_locate_setinterests(OscarSession *sess, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy); -/* 0x0015 */ faim_export int aim_locate_getinfoshort(OscarSession *sess, const char *sn, guint32 flags); +/* 0x0002 */ int aim_locate_reqrights(OscarData *od); +/* 0x0004 */ int aim_locate_setcaps(OscarData *od, guint32 caps); +/* 0x0004 */ int aim_locate_setprofile(OscarData *od, const char *profile_encoding, const gchar *profile, const int profile_len, const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len); +/* 0x0005 */ int aim_locate_getinfo(OscarData *od, const char *, guint16); +/* 0x0009 */ int aim_locate_setdirinfo(OscarData *od, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy); +/* 0x000b */ int aim_locate_000b(OscarData *od, const char *sn); +/* 0x000f */ int aim_locate_setinterests(OscarData *od, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy); +/* 0x0015 */ int aim_locate_getinfoshort(OscarData *od, const char *sn, guint32 flags); + +void aim_locate_requestuserinfo(OscarData *od, const char *sn); +guint32 aim_locate_getcaps(OscarData *od, ByteStream *bs, int len); +guint32 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len); +void aim_info_free(aim_userinfo_t *); +int aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *); +int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info); /* 0x0003 - family_buddy.c */ -/* 0x0002 */ faim_export int aim_buddylist_reqrights(OscarSession *, OscarConnection *); -/* 0x0004 */ faim_export int aim_buddylist_set(OscarSession *, OscarConnection *, const char *); -/* 0x0004 */ faim_export int aim_buddylist_addbuddy(OscarSession *, OscarConnection *, const char *); -/* 0x0005 */ faim_export int aim_buddylist_removebuddy(OscarSession *, OscarConnection *, const char *); -/* 0x000b */ faim_export int aim_buddylist_oncoming(OscarSession *sess, OscarConnection *conn, aim_userinfo_t *info); -/* 0x000c */ faim_export int aim_buddylist_offgoing(OscarSession *sess, OscarConnection *conn, const char *sn); +/* 0x0002 */ int aim_buddylist_reqrights(OscarData *, FlapConnection *); +/* 0x0004 */ int aim_buddylist_set(OscarData *, FlapConnection *, const char *); +/* 0x0004 */ int aim_buddylist_addbuddy(OscarData *, FlapConnection *, const char *); +/* 0x0005 */ int aim_buddylist_removebuddy(OscarData *, FlapConnection *, const char *); /* 0x000a - family_userlookup.c */ -faim_export int aim_search_address(OscarSession *, OscarConnection *, const char *); +int aim_search_address(OscarData *, const char *); @@ -1136,16 +1028,16 @@ #define AIM_CHATFLAGS_NOREFLECT 0x0001 #define AIM_CHATFLAGS_AWAY 0x0002 -faim_export int aim_chat_send_im(OscarSession *sess, OscarConnection *conn, guint16 flags, const gchar *msg, int msglen, const char *encoding, const char *language); -faim_export int aim_chat_join(OscarSession *sess, OscarConnection *conn, guint16 exchange, const char *roomname, guint16 instance); -faim_export int aim_chat_attachname(OscarConnection *conn, guint16 exchange, const char *roomname, guint16 instance); -faim_export char *aim_chat_getname(OscarConnection *conn); -faim_export OscarConnection *aim_chat_getconn(OscarSession *, const char *name); +int aim_chat_send_im(OscarData *od, FlapConnection *conn, guint16 flags, const gchar *msg, int msglen, const char *encoding, const char *language); +int aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance); +int aim_chat_attachname(FlapConnection *conn, guint16 exchange, const char *roomname, guint16 instance); +char *aim_chat_getname(FlapConnection *conn); +FlapConnection *aim_chat_getconn(OscarData *, const char *name); -faim_export int aim_chatnav_reqrights(OscarSession *sess, OscarConnection *conn); +int aim_chatnav_reqrights(OscarData *od, FlapConnection *conn); -faim_export int aim_chatnav_createroom(OscarSession *sess, OscarConnection *conn, const char *name, guint16 exchange); -faim_export int aim_chat_leaveroom(OscarSession *sess, const char *name); +int aim_chatnav_createroom(OscarData *od, FlapConnection *conn, const char *name, guint16 exchange); +int aim_chat_leaveroom(OscarData *od, const char *name); @@ -1169,15 +1061,15 @@ struct aim_odir *next; }; -faim_export int aim_odir_email(OscarSession *, const char *, const char *); -faim_export int aim_odir_name(OscarSession *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *); -faim_export int aim_odir_interest(OscarSession *, const char *, const char *); +int aim_odir_email(OscarData *, const char *, const char *); +int aim_odir_name(OscarData *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *); +int aim_odir_interest(OscarData *, const char *, const char *); /* 0x0010 - family_bart.c */ -faim_export int aim_bart_upload(OscarSession *sess, const guint8 *icon, guint16 iconlen); -faim_export int aim_bart_request(OscarSession *sess, const char *sn, guint8 iconcsumtype, const guint8 *iconstr, guint16 iconstrlen); +int aim_bart_upload(OscarData *od, const guint8 *icon, guint16 iconlen); +int aim_bart_request(OscarData *od, const char *sn, guint8 iconcsumtype, const guint8 *iconstr, guint16 iconstrlen); @@ -1221,45 +1113,45 @@ }; /* These build the actual SNACs and queue them to be sent */ -/* 0x0002 */ faim_export int aim_ssi_reqrights(OscarSession *sess); -/* 0x0004 */ faim_export int aim_ssi_reqdata(OscarSession *sess); -/* 0x0005 */ faim_export int aim_ssi_reqifchanged(OscarSession *sess, time_t localstamp, guint16 localrev); -/* 0x0007 */ faim_export int aim_ssi_enable(OscarSession *sess); -/* 0x0008 */ faim_export int aim_ssi_addmoddel(OscarSession *sess); -/* 0x0011 */ faim_export int aim_ssi_modbegin(OscarSession *sess); -/* 0x0012 */ faim_export int aim_ssi_modend(OscarSession *sess); -/* 0x0014 */ faim_export int aim_ssi_sendauth(OscarSession *sess, char *sn, char *msg); -/* 0x0018 */ faim_export int aim_ssi_sendauthrequest(OscarSession *sess, char *sn, const char *msg); -/* 0x001a */ faim_export int aim_ssi_sendauthreply(OscarSession *sess, char *sn, guint8 reply, const char *msg); +/* 0x0002 */ int aim_ssi_reqrights(OscarData *od); +/* 0x0004 */ int aim_ssi_reqdata(OscarData *od); +/* 0x0005 */ int aim_ssi_reqifchanged(OscarData *od, time_t localstamp, guint16 localrev); +/* 0x0007 */ int aim_ssi_enable(OscarData *od); +/* 0x0008 */ int aim_ssi_addmoddel(OscarData *od); +/* 0x0011 */ int aim_ssi_modbegin(OscarData *od); +/* 0x0012 */ int aim_ssi_modend(OscarData *od); +/* 0x0014 */ int aim_ssi_sendauth(OscarData *od, char *sn, char *msg); +/* 0x0018 */ int aim_ssi_sendauthrequest(OscarData *od, char *sn, const char *msg); +/* 0x001a */ int aim_ssi_sendauthreply(OscarData *od, char *sn, guint8 reply, const char *msg); /* Client functions for retrieving SSI data */ -faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid); -faim_export struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, guint16 type); -faim_export struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn); -faim_export char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn); -faim_export int aim_ssi_getpermdeny(struct aim_ssi_item *list); -faim_export guint32 aim_ssi_getpresence(struct aim_ssi_item *list); -faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn); -faim_export char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn); -faim_export int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn); +struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid); +struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, guint16 type); +struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn); +char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn); +int aim_ssi_getpermdeny(struct aim_ssi_item *list); +guint32 aim_ssi_getpresence(struct aim_ssi_item *list); +char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn); +char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn); +int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn); /* Client functions for changing SSI data */ -faim_export int aim_ssi_addbuddy(OscarSession *sess, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth); -faim_export int aim_ssi_addpermit(OscarSession *sess, const char *name); -faim_export int aim_ssi_adddeny(OscarSession *sess, const char *name); -faim_export int aim_ssi_delbuddy(OscarSession *sess, const char *name, const char *group); -faim_export int aim_ssi_delpermit(OscarSession *sess, const char *name); -faim_export int aim_ssi_deldeny(OscarSession *sess, const char *name); -faim_export int aim_ssi_movebuddy(OscarSession *sess, const char *oldgn, const char *newgn, const char *sn); -faim_export int aim_ssi_aliasbuddy(OscarSession *sess, const char *gn, const char *sn, const char *alias); -faim_export int aim_ssi_editcomment(OscarSession *sess, const char *gn, const char *sn, const char *alias); -faim_export int aim_ssi_rename_group(OscarSession *sess, const char *oldgn, const char *newgn); -faim_export int aim_ssi_cleanlist(OscarSession *sess); -faim_export int aim_ssi_deletelist(OscarSession *sess); -faim_export int aim_ssi_setpermdeny(OscarSession *sess, guint8 permdeny, guint32 vismask); -faim_export int aim_ssi_setpresence(OscarSession *sess, guint32 presence); -faim_export int aim_ssi_seticon(OscarSession *sess, guint8 *iconsum, guint16 iconsumlen); -faim_export int aim_ssi_delicon(OscarSession *sess); +int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth); +int aim_ssi_addpermit(OscarData *od, const char *name); +int aim_ssi_adddeny(OscarData *od, const char *name); +int aim_ssi_delbuddy(OscarData *od, const char *name, const char *group); +int aim_ssi_delpermit(OscarData *od, const char *name); +int aim_ssi_deldeny(OscarData *od, const char *name); +int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *sn); +int aim_ssi_aliasbuddy(OscarData *od, const char *gn, const char *sn, const char *alias); +int aim_ssi_editcomment(OscarData *od, const char *gn, const char *sn, const char *alias); +int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn); +int aim_ssi_cleanlist(OscarData *od); +int aim_ssi_deletelist(OscarData *od); +int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny, guint32 vismask); +int aim_ssi_setpresence(OscarData *od, guint32 presence); +int aim_ssi_seticon(OscarData *od, guint8 *iconsum, guint16 iconsumlen); +int aim_ssi_delicon(OscarData *od); @@ -1345,23 +1237,23 @@ struct aim_icq_info *next; }; -faim_export int aim_icq_reqofflinemsgs(OscarSession *sess); -faim_export int aim_icq_ackofflinemsgs(OscarSession *sess); -faim_export int aim_icq_setsecurity(OscarSession *sess, gboolean auth_required, gboolean webaware); -faim_export int aim_icq_changepasswd(OscarSession *sess, const char *passwd); -faim_export int aim_icq_getsimpleinfo(OscarSession *sess, const char *uin); -faim_export int aim_icq_getalias(OscarSession *sess, const char *uin); -faim_export int aim_icq_getallinfo(OscarSession *sess, const char *uin); +int aim_icq_reqofflinemsgs(OscarData *od); +int aim_icq_ackofflinemsgs(OscarData *od); +int aim_icq_setsecurity(OscarData *od, gboolean auth_required, gboolean webaware); +int aim_icq_changepasswd(OscarData *od, const char *passwd); +int aim_icq_getsimpleinfo(OscarData *od, const char *uin); +int aim_icq_getalias(OscarData *od, const char *uin); +int aim_icq_getallinfo(OscarData *od, const char *uin); /* 0x0017 - family_auth.c */ -faim_export int aim_sendcookie(OscarSession *, OscarConnection *, const guint16 length, const guint8 *); -faim_export int aim_admin_changepasswd(OscarSession *, OscarConnection *, const char *newpw, const char *curpw); -faim_export int aim_admin_reqconfirm(OscarSession *sess, OscarConnection *conn); -faim_export int aim_admin_getinfo(OscarSession *sess, OscarConnection *conn, guint16 info); -faim_export int aim_admin_setemail(OscarSession *sess, OscarConnection *conn, const char *newemail); -faim_export int aim_admin_setnick(OscarSession *sess, OscarConnection *conn, const char *newnick); +void aim_sendcookie(OscarData *, FlapConnection *, const guint16 length, const guint8 *); +int aim_admin_changepasswd(OscarData *, FlapConnection *, const char *newpw, const char *curpw); +int aim_admin_reqconfirm(OscarData *od, FlapConnection *conn); +int aim_admin_getinfo(OscarData *od, FlapConnection *conn, guint16 info); +int aim_admin_setemail(OscarData *od, FlapConnection *conn, const char *newemail); +int aim_admin_setnick(OscarData *od, FlapConnection *conn, const char *newnick); @@ -1378,8 +1270,8 @@ struct aim_emailinfo *next; }; -faim_export int aim_email_sendcookies(OscarSession *sess); -faim_export int aim_email_activate(OscarSession *sess); +int aim_email_sendcookies(OscarData *od); +int aim_email_activate(OscarData *od); @@ -1401,55 +1293,49 @@ } aim_tlvlist_t; /* TLV handling functions */ -faim_internal aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, guint16 type, const int nth); -faim_internal int aim_tlv_getlength(aim_tlvlist_t *list, guint16 type, const int nth); -faim_internal char *aim_tlv_getstr(aim_tlvlist_t *list, const guint16 type, const int nth); -faim_internal guint8 aim_tlv_get8(aim_tlvlist_t *list, const guint16 type, const int nth); -faim_internal guint16 aim_tlv_get16(aim_tlvlist_t *list, const guint16 type, const int nth); -faim_internal guint32 aim_tlv_get32(aim_tlvlist_t *list, const guint16 type, const int nth); +aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, guint16 type, const int nth); +int aim_tlv_getlength(aim_tlvlist_t *list, guint16 type, const int nth); +char *aim_tlv_getstr(aim_tlvlist_t *list, const guint16 type, const int nth); +guint8 aim_tlv_get8(aim_tlvlist_t *list, const guint16 type, const int nth); +guint16 aim_tlv_get16(aim_tlvlist_t *list, const guint16 type, const int nth); +guint32 aim_tlv_get32(aim_tlvlist_t *list, const guint16 type, const int nth); /* TLV list handling functions */ -faim_internal aim_tlvlist_t *aim_tlvlist_read(ByteStream *bs); -faim_internal aim_tlvlist_t *aim_tlvlist_readnum(ByteStream *bs, guint16 num); -faim_internal aim_tlvlist_t *aim_tlvlist_readlen(ByteStream *bs, guint16 len); -faim_internal aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig); +aim_tlvlist_t *aim_tlvlist_read(ByteStream *bs); +aim_tlvlist_t *aim_tlvlist_readnum(ByteStream *bs, guint16 num); +aim_tlvlist_t *aim_tlvlist_readlen(ByteStream *bs, guint16 len); +aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig); -faim_internal int aim_tlvlist_count(aim_tlvlist_t **list); -faim_internal int aim_tlvlist_size(aim_tlvlist_t **list); -faim_internal int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two); -faim_internal int aim_tlvlist_write(ByteStream *bs, aim_tlvlist_t **list); -faim_internal void aim_tlvlist_free(aim_tlvlist_t **list); +int aim_tlvlist_count(aim_tlvlist_t **list); +int aim_tlvlist_size(aim_tlvlist_t **list); +int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two); +int aim_tlvlist_write(ByteStream *bs, aim_tlvlist_t **list); +void aim_tlvlist_free(aim_tlvlist_t **list); -faim_internal int aim_tlvlist_add_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value); -faim_internal int aim_tlvlist_add_noval(aim_tlvlist_t **list, const guint16 type); -faim_internal int aim_tlvlist_add_8(aim_tlvlist_t **list, const guint16 type, const guint8 value); -faim_internal int aim_tlvlist_add_16(aim_tlvlist_t **list, const guint16 type, const guint16 value); -faim_internal int aim_tlvlist_add_32(aim_tlvlist_t **list, const guint16 type, const guint32 value); -faim_internal int aim_tlvlist_add_str(aim_tlvlist_t **list, const guint16 type, const char *value); -faim_internal int aim_tlvlist_add_caps(aim_tlvlist_t **list, const guint16 type, const guint32 caps); -faim_internal int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *userinfo); -faim_internal int aim_tlvlist_add_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance); -faim_internal int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl); +int aim_tlvlist_add_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value); +int aim_tlvlist_add_noval(aim_tlvlist_t **list, const guint16 type); +int aim_tlvlist_add_8(aim_tlvlist_t **list, const guint16 type, const guint8 value); +int aim_tlvlist_add_16(aim_tlvlist_t **list, const guint16 type, const guint16 value); +int aim_tlvlist_add_32(aim_tlvlist_t **list, const guint16 type, const guint32 value); +int aim_tlvlist_add_str(aim_tlvlist_t **list, const guint16 type, const char *value); +int aim_tlvlist_add_caps(aim_tlvlist_t **list, const guint16 type, const guint32 caps); +int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *userinfo); +int aim_tlvlist_add_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance); +int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl); -faim_internal int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const guint16 type, const guint16 lenth, const guint8 *value); -faim_internal int aim_tlvlist_replace_str(aim_tlvlist_t **list, const guint16 type, const char *str); -faim_internal int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const guint16 type); -faim_internal int aim_tlvlist_replace_8(aim_tlvlist_t **list, const guint16 type, const guint8 value); -faim_internal int aim_tlvlist_replace_16(aim_tlvlist_t **list, const guint16 type, const guint16 value); -faim_internal int aim_tlvlist_replace_32(aim_tlvlist_t **list, const guint16 type, const guint32 value); +int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const guint16 type, const guint16 lenth, const guint8 *value); +int aim_tlvlist_replace_str(aim_tlvlist_t **list, const guint16 type, const char *str); +int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const guint16 type); +int aim_tlvlist_replace_8(aim_tlvlist_t **list, const guint16 type, const guint8 value); +int aim_tlvlist_replace_16(aim_tlvlist_t **list, const guint16 type, const guint16 value); +int aim_tlvlist_replace_32(aim_tlvlist_t **list, const guint16 type, const guint32 value); -faim_internal void aim_tlvlist_remove(aim_tlvlist_t **list, const guint16 type); +void aim_tlvlist_remove(aim_tlvlist_t **list, const guint16 type); /* util.c */ -/* - * These are really ugly. You'd think this was LISP. I wish it was. - * - * XXX With the advent of bstream's, these should be removed to enforce - * their use. - * - */ +/* These are really ugly. You'd think this was LISP. I wish it was. */ #define aimutil_put8(buf, data) ((*(buf) = (guint8)(data)&0xff),1) #define aimutil_get8(buf) ((*(buf))&0xff) #define aimutil_put16(buf, data) ( \ @@ -1495,18 +1381,193 @@ (((*((buf)+2)) << 16) & 0x00ff0000) + \ (((*((buf)+3)) << 24) & 0xff000000)) -faim_export guint16 aimutil_iconsum(const guint8 *buf, int buflen); -faim_export int aimutil_tokslen(char *toSearch, int theindex, char dl); -faim_export int aimutil_itemcnt(char *toSearch, char dl); -faim_export char *aimutil_itemindex(char *toSearch, int theindex, char dl); +guint16 aimutil_iconsum(const guint8 *buf, int buflen); +int aimutil_tokslen(char *toSearch, int theindex, char dl); +int aimutil_itemcnt(char *toSearch, char dl); +char *aimutil_itemindex(char *toSearch, int theindex, char dl); + +int aim_snvalid(const char *sn); +int aim_sn_is_icq(const char *sn); +int aim_sn_is_sms(const char *sn); +int aim_snlen(const char *sn); +int aim_sncmp(const char *sn1, const char *sn2); + + + + +typedef struct { + guint16 family; + guint16 subtype; + guint16 flags; + guint32 id; +} aim_modsnac_t; + +#define AIM_MODULENAME_MAXLEN 16 +#define AIM_MODFLAG_MULTIFAMILY 0x0001 +typedef struct aim_module_s +{ + guint16 family; + guint16 version; + guint16 toolid; + guint16 toolversion; + guint16 flags; + char name[AIM_MODULENAME_MAXLEN+1]; + int (*snachandler)(OscarData *od, FlapConnection *conn, struct aim_module_s *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs); + void (*shutdown)(OscarData *od, struct aim_module_s *mod); + void *priv; + struct aim_module_s *next; +} aim_module_t; + +int aim__registermodule(OscarData *od, int (*modfirst)(OscarData *, aim_module_t *)); +void aim__shutdownmodules(OscarData *od); +aim_module_t *aim__findmodulebygroup(OscarData *od, guint16 group); +aim_module_t *aim__findmodule(OscarData *od, const char *name); + +int admin_modfirst(OscarData *od, aim_module_t *mod); +int buddylist_modfirst(OscarData *od, aim_module_t *mod); +int bos_modfirst(OscarData *od, aim_module_t *mod); +int search_modfirst(OscarData *od, aim_module_t *mod); +int stats_modfirst(OscarData *od, aim_module_t *mod); +int auth_modfirst(OscarData *od, aim_module_t *mod); +int msg_modfirst(OscarData *od, aim_module_t *mod); +int misc_modfirst(OscarData *od, aim_module_t *mod); +int chatnav_modfirst(OscarData *od, aim_module_t *mod); +int chat_modfirst(OscarData *od, aim_module_t *mod); +int locate_modfirst(OscarData *od, aim_module_t *mod); +int service_modfirst(OscarData *od, aim_module_t *mod); +int invite_modfirst(OscarData *od, aim_module_t *mod); +int translate_modfirst(OscarData *od, aim_module_t *mod); +int popups_modfirst(OscarData *od, aim_module_t *mod); +int adverts_modfirst(OscarData *od, aim_module_t *mod); +int odir_modfirst(OscarData *od, aim_module_t *mod); +int bart_modfirst(OscarData *od, aim_module_t *mod); +int ssi_modfirst(OscarData *od, aim_module_t *mod); +int icq_modfirst(OscarData *od, aim_module_t *mod); +int email_modfirst(OscarData *od, aim_module_t *mod); + +int aim_genericreq_n(OscarData *, FlapConnection *conn, guint16 family, guint16 subtype); +int aim_genericreq_n_snacid(OscarData *, FlapConnection *conn, guint16 family, guint16 subtype); +int aim_genericreq_l(OscarData *, FlapConnection *conn, guint16 family, guint16 subtype, guint32 *); +int aim_genericreq_s(OscarData *, FlapConnection *conn, guint16 family, guint16 subtype, guint16 *); -faim_export int aim_snvalid(const char *sn); -faim_export int aim_sn_is_icq(const char *sn); -faim_export int aim_sn_is_sms(const char *sn); -faim_export int aim_snlen(const char *sn); -faim_export int aim_sncmp(const char *sn1, const char *sn2); +/* bstream.c */ +int byte_stream_init(ByteStream *bs, guint8 *data, int len); +int byte_stream_empty(ByteStream *bs); +int byte_stream_curpos(ByteStream *bs); +int byte_stream_setpos(ByteStream *bs, unsigned int off); +void byte_stream_rewind(ByteStream *bs); +int byte_stream_advance(ByteStream *bs, int n); +guint8 byte_stream_get8(ByteStream *bs); +guint16 byte_stream_get16(ByteStream *bs); +guint32 byte_stream_get32(ByteStream *bs); +guint8 byte_stream_getle8(ByteStream *bs); +guint16 byte_stream_getle16(ByteStream *bs); +guint32 byte_stream_getle32(ByteStream *bs); +int byte_stream_getrawbuf(ByteStream *bs, guint8 *buf, int len); +guint8 *byte_stream_getraw(ByteStream *bs, int len); +char *byte_stream_getstr(ByteStream *bs, int len); +int byte_stream_put8(ByteStream *bs, guint8 v); +int byte_stream_put16(ByteStream *bs, guint16 v); +int byte_stream_put32(ByteStream *bs, guint32 v); +int byte_stream_putle8(ByteStream *bs, guint8 v); +int byte_stream_putle16(ByteStream *bs, guint16 v); +int byte_stream_putle32(ByteStream *bs, guint32 v); +int byte_stream_putraw(ByteStream *bs, const guint8 *v, int len); +int byte_stream_putstr(ByteStream *bs, const char *str); +int byte_stream_putbs(ByteStream *bs, ByteStream *srcbs, int len); +int byte_stream_putcaps(ByteStream *bs, guint32 caps); + +/* rxhandlers.c */ +aim_rxcallback_t aim_callhandler(OscarData *od, guint16 family, guint16 type); + +/* + * Generic SNAC structure. Rarely if ever used. + */ +typedef struct aim_snac_s { + aim_snacid_t id; + guint16 family; + guint16 type; + guint16 flags; + void *data; + time_t issuetime; + struct aim_snac_s *next; +} aim_snac_t; + +/* snac.c */ +void aim_initsnachash(OscarData *od); +aim_snacid_t aim_newsnac(OscarData *, aim_snac_t *newsnac); +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 *aim_remsnac(OscarData *, aim_snacid_t id); +int aim_putsnac(ByteStream *, guint16 family, guint16 type, guint16 flags, aim_snacid_t id); + +struct chatsnacinfo { + guint16 exchange; + char name[128]; + guint16 instance; +}; -#include "oscar_internal.h" +/* + * In SNACland, the terms 'family' and 'group' are synonymous -- the former + * is my term, the latter is AOL's. + */ +struct snacgroup { + guint16 group; + struct snacgroup *next; +}; + +struct snacpair { + guint16 group; + guint16 subtype; + struct snacpair *next; +}; + +struct rateclass { + guint16 classid; + guint32 windowsize; + guint32 clear; + guint32 alert; + guint32 limit; + guint32 disconnect; + guint32 current; + guint32 max; + guint8 unknown[5]; /* only present in versions >= 3 */ + struct snacpair *members; + struct rateclass *next; +}; + +/* + * This is inside every connection. But it is a void * to anything + * outside of libfaim. It should remain that way. It's called data + * abstraction. Maybe you've heard of it. (Probably not if you're a + * libfaim user.) + * + */ +typedef struct aim_conn_inside_s { + struct snacgroup *groups; + struct rateclass *rates; +} aim_conn_inside_t; + +int aim_cachecookie(OscarData *od, IcbmCookie *cookie); +IcbmCookie *aim_uncachecookie(OscarData *od, guint8 *cookie, int type); +IcbmCookie *aim_mkcookie(guint8 *, int, void *); +IcbmCookie *aim_checkcookie(OscarData *, const unsigned char *, const int); +int aim_freecookie(OscarData *od, IcbmCookie *cookie); +int aim_msgcookie_gettype(int type); +int aim_cookie_free(OscarData *od, IcbmCookie *cookie); + +int aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo); + +void flap_connection_destroy_chat(OscarData *od, FlapConnection *conn); + +/* These are all handled internally now. */ +int aim_setversions(OscarData *od, FlapConnection *conn); +int aim_reqrates(OscarData *, FlapConnection *); +int aim_rates_addparam(OscarData *, FlapConnection *); +int aim_rates_delparam(OscarData *, FlapConnection *); + + + + #ifdef __cplusplus }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/oscar/oscar_data.c Fri Apr 07 05:10:56 2006 +0000 @@ -0,0 +1,158 @@ +/* + * 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 +*/ + +#include "oscar.h" + +typedef struct _SnacHandler SnacHandler; + +struct _SnacHandler +{ + guint16 family; + guint16 type; + aim_rxcallback_t handler; + guint16 flags; +}; + +static void +oscar_free_buddyinfo(void *data) +{ + struct buddyinfo *bi = data; + g_free(bi); +} + +/** + * Allocates a new OscarData and initializes it with default values. + */ +OscarData * +oscar_data_new(void) +{ + OscarData *od; + + od = g_new0(OscarData, 1); + + aim_initsnachash(od); + od->snacid_next = 0x00000001; + od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, oscar_free_buddyinfo); + + /* + * Register all the modules for this session... + */ + aim__registermodule(od, misc_modfirst); /* load the catch-all first */ + aim__registermodule(od, service_modfirst); + aim__registermodule(od, locate_modfirst); + aim__registermodule(od, buddylist_modfirst); + aim__registermodule(od, msg_modfirst); + aim__registermodule(od, adverts_modfirst); + aim__registermodule(od, invite_modfirst); + aim__registermodule(od, admin_modfirst); + aim__registermodule(od, popups_modfirst); + aim__registermodule(od, bos_modfirst); + aim__registermodule(od, search_modfirst); + aim__registermodule(od, stats_modfirst); + aim__registermodule(od, translate_modfirst); + aim__registermodule(od, chatnav_modfirst); + aim__registermodule(od, chat_modfirst); + aim__registermodule(od, odir_modfirst); + aim__registermodule(od, bart_modfirst); + /* missing 0x11 - 0x12 */ + aim__registermodule(od, ssi_modfirst); + /* missing 0x14 */ + aim__registermodule(od, icq_modfirst); + /* missing 0x16 */ + aim__registermodule(od, auth_modfirst); + aim__registermodule(od, email_modfirst); + + return od; +} + +/** + * Logoff and deallocate a session. + * + * @param od Session to kill + */ +void +oscar_data_destroy(OscarData *od) +{ + aim_cleansnacs(od, -1); + + while (od->oscar_connections != NULL) + flap_connection_destroy(od->oscar_connections->data); + + while (od->peer_connections != NULL) + peer_connection_destroy(od->peer_connections->data, + PEER_DISCONNECT_LOCAL_CLOSED); + + if (od->handlerlist != NULL) + aim_clearhandlers(od); + + aim__shutdownmodules(od); + + g_hash_table_destroy(od->buddyinfo); + + g_free(od); +} + +int oscar_data_addhandler(OscarData *od, guint16 family, guint16 type, aim_rxcallback_t newhandler, guint16 flags) +{ + SnacHandler *snac_handler; + + gaim_debug_misc("oscar", "Adding handler for %04x/%04x\n", family, type); + + snac_handler = g_new0(SnacHandler, 1); + + snac_handler->family = family; + snac_handler->type = type; + snac_handler->flags = flags; + snac_handler->handler = newhandler; + + od->handlerlist = g_list_prepend(od->handlerlist, snac_handler); + + return 0; +} + +void +aim_clearhandlers(OscarData *od) +{ + SnacHandler *snac_handler; + + while (od->handlerlist != NULL) + { + snac_handler = od->handlerlist->data; + od->handlerlist = g_list_remove(od->handlerlist, snac_handler); + g_free(snac_handler); + } + od->handlerlist = NULL; +} + +aim_rxcallback_t +aim_callhandler(OscarData *od, guint16 family, guint16 type) +{ + GList *cur; + SnacHandler *snac_handler; + + for (cur = od->handlerlist; cur != NULL; cur = cur->next) + { + snac_handler = cur->data; + if ((snac_handler->family == family) && (snac_handler->type == type)) + return snac_handler->handler; + } + + return NULL; +}
--- a/src/protocols/oscar/oscar_internal.h Fri Apr 07 01:05:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -/* - * 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 -*/ - -/* - * oscar_internal.h -- prototypes/structs for the guts of libfaim - * - */ - -#ifndef _OSCAR_INTERNAL_H_ -#define _OSCAR_INTERNAL_H_ - -typedef struct { - guint16 family; - guint16 subtype; - guint16 flags; - guint32 id; -} aim_modsnac_t; - -#define AIM_MODULENAME_MAXLEN 16 -#define AIM_MODFLAG_MULTIFAMILY 0x0001 -typedef struct aim_module_s { - guint16 family; - guint16 version; - guint16 toolid; - guint16 toolversion; - guint16 flags; - char name[AIM_MODULENAME_MAXLEN+1]; - int (*snachandler)(OscarSession *sess, struct aim_module_s *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs); - - void (*shutdown)(OscarSession *sess, struct aim_module_s *mod); - void *priv; - struct aim_module_s *next; -} aim_module_t; - -faim_internal int aim__registermodule(OscarSession *sess, int (*modfirst)(OscarSession *, aim_module_t *)); -faim_internal void aim__shutdownmodules(OscarSession *sess); -faim_internal aim_module_t *aim__findmodulebygroup(OscarSession *sess, guint16 group); -faim_internal aim_module_t *aim__findmodule(OscarSession *sess, const char *name); - -faim_internal int admin_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int buddylist_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int bos_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int search_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int stats_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int auth_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int msg_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int misc_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int chatnav_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int chat_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int locate_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int service_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int invite_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int translate_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int popups_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int adverts_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int odir_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int bart_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int ssi_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int icq_modfirst(OscarSession *sess, aim_module_t *mod); -faim_internal int email_modfirst(OscarSession *sess, aim_module_t *mod); - -faim_internal int aim_genericreq_n(OscarSession *, OscarConnection *conn, guint16 family, guint16 subtype); -faim_internal int aim_genericreq_n_snacid(OscarSession *, OscarConnection *conn, guint16 family, guint16 subtype); -faim_internal int aim_genericreq_l(OscarSession *, OscarConnection *conn, guint16 family, guint16 subtype, guint32 *); -faim_internal int aim_genericreq_s(OscarSession *, OscarConnection *conn, guint16 family, guint16 subtype, guint16 *); - -/* bstream.c */ -faim_internal int aim_bstream_init(ByteStream *bs, guint8 *data, int len); -faim_internal int aim_bstream_empty(ByteStream *bs); -faim_internal int aim_bstream_curpos(ByteStream *bs); -faim_internal int aim_bstream_setpos(ByteStream *bs, unsigned int off); -faim_internal void aim_bstream_rewind(ByteStream *bs); -faim_internal int aim_bstream_advance(ByteStream *bs, int n); -faim_internal guint8 aimbs_get8(ByteStream *bs); -faim_internal guint16 aimbs_get16(ByteStream *bs); -faim_internal guint32 aimbs_get32(ByteStream *bs); -faim_internal guint8 aimbs_getle8(ByteStream *bs); -faim_internal guint16 aimbs_getle16(ByteStream *bs); -faim_internal guint32 aimbs_getle32(ByteStream *bs); -faim_internal int aimbs_getrawbuf(ByteStream *bs, guint8 *buf, int len); -faim_internal guint8 *aimbs_getraw(ByteStream *bs, int len); -faim_internal char *aimbs_getstr(ByteStream *bs, int len); -faim_internal int aimbs_put8(ByteStream *bs, guint8 v); -faim_internal int aimbs_put16(ByteStream *bs, guint16 v); -faim_internal int aimbs_put32(ByteStream *bs, guint32 v); -faim_internal int aimbs_putle8(ByteStream *bs, guint8 v); -faim_internal int aimbs_putle16(ByteStream *bs, guint16 v); -faim_internal int aimbs_putle32(ByteStream *bs, guint32 v); -faim_internal int aimbs_putraw(ByteStream *bs, const guint8 *v, int len); -faim_internal int aimbs_putstr(ByteStream *bs, const char *str); -faim_internal int aimbs_putbs(ByteStream *bs, ByteStream *srcbs, int len); -faim_internal int aimbs_putcaps(ByteStream *bs, guint32 caps); - -/* conn.c */ -faim_internal OscarConnection *aim_cloneconn(OscarSession *sess, OscarConnection *src); - -/* rxhandlers.c */ -faim_internal aim_rxcallback_t aim_callhandler(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 type); -faim_internal int aim_callhandler_noparam(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 type, FlapFrame *ptr); -faim_internal int aim_parse_unknown(OscarSession *, FlapFrame *, ...); -faim_internal void aim_clonehandlers(OscarSession *sess, OscarConnection *dest, OscarConnection *src); - -/* rxqueue.c */ -faim_internal int aim_recv(int fd, void *buf, size_t count); -faim_internal int aim_bstream_recv(ByteStream *bs, int fd, size_t count); -faim_internal void aim_rxqueue_cleanbyconn(OscarSession *sess, OscarConnection *conn); -faim_internal void aim_frame_destroy(FlapFrame *); - -/* txqueue.c */ -faim_internal FlapFrame *flap_frame_new(OscarSession *sess, OscarConnection *conn, guint8 framing, guint16 chan, int datalen); -faim_internal int aim_tx_enqueue(OscarSession *, FlapFrame *); -faim_internal int aim_bstream_send(ByteStream *bs, OscarConnection *conn, size_t count); -faim_internal void aim_tx_cleanqueue(OscarSession *, OscarConnection *); - -/* - * Generic SNAC structure. Rarely if ever used. - */ -typedef struct aim_snac_s { - aim_snacid_t id; - guint16 family; - guint16 type; - guint16 flags; - void *data; - time_t issuetime; - struct aim_snac_s *next; -} aim_snac_t; - -/* snac.c */ -faim_internal void aim_initsnachash(OscarSession *sess); -faim_internal aim_snacid_t aim_newsnac(OscarSession *, aim_snac_t *newsnac); -faim_internal aim_snacid_t aim_cachesnac(OscarSession *sess, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen); -faim_internal aim_snac_t *aim_remsnac(OscarSession *, aim_snacid_t id); -faim_internal int aim_putsnac(ByteStream *, guint16 family, guint16 type, guint16 flags, aim_snacid_t id); - -struct chatsnacinfo { - guint16 exchange; - char name[128]; - guint16 instance; -}; - -/* - * In SNACland, the terms 'family' and 'group' are synonymous -- the former - * is my term, the latter is AOL's. - */ -struct snacgroup { - guint16 group; - struct snacgroup *next; -}; - -struct snacpair { - guint16 group; - guint16 subtype; - struct snacpair *next; -}; - -struct rateclass { - guint16 classid; - guint32 windowsize; - guint32 clear; - guint32 alert; - guint32 limit; - guint32 disconnect; - guint32 current; - guint32 max; - guint8 unknown[5]; /* only present in versions >= 3 */ - struct snacpair *members; - struct rateclass *next; -}; - -/* - * This is inside every connection. But it is a void * to anything - * outside of libfaim. It should remain that way. It's called data - * abstraction. Maybe you've heard of it. (Probably not if you're a - * libfaim user.) - * - */ -typedef struct aim_conn_inside_s { - struct snacgroup *groups; - struct rateclass *rates; -} aim_conn_inside_t; - -faim_internal void aim_conn_addgroup(OscarConnection *conn, guint16 group); - -faim_internal int aim_cachecookie(OscarSession *sess, IcbmCookie *cookie); -faim_internal IcbmCookie *aim_uncachecookie(OscarSession *sess, guint8 *cookie, int type); -faim_internal IcbmCookie *aim_mkcookie(guint8 *, int, void *); -faim_internal IcbmCookie *aim_checkcookie(OscarSession *, const unsigned char *, const int); -faim_internal int aim_freecookie(OscarSession *sess, IcbmCookie *cookie); -faim_internal int aim_msgcookie_gettype(int reqclass); -faim_internal int aim_cookie_free(OscarSession *sess, IcbmCookie *cookie); - -/* 0x0002 - locate.c */ -faim_internal void aim_locate_requestuserinfo(OscarSession *sess, const char *sn); -faim_internal guint32 aim_locate_getcaps(OscarSession *sess, ByteStream *bs, int len); -faim_internal guint32 aim_locate_getcaps_short(OscarSession *sess, ByteStream *bs, int len); -faim_internal void aim_info_free(aim_userinfo_t *); -faim_internal int aim_info_extract(OscarSession *sess, ByteStream *bs, aim_userinfo_t *); -faim_internal int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info); - -faim_internal int aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo); - -faim_internal void oscar_connection_destroy_chat(OscarSession *sess, OscarConnection *conn); - -/* These are all handled internally now. */ -faim_internal int aim_setversions(OscarSession *sess, OscarConnection *conn); -faim_internal int aim_reqrates(OscarSession *, OscarConnection *); -faim_internal int aim_rates_addparam(OscarSession *, OscarConnection *); -faim_internal int aim_rates_delparam(OscarSession *, OscarConnection *); - -#endif /* _OSCAR_INTERNAL_H_ */
--- a/src/protocols/oscar/peer.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/peer.c Fri Apr 07 05:10:56 2006 +0000 @@ -19,59 +19,33 @@ */ /* - * Oscar File transfer (OFT) and Oscar Direct Connect (ODC). - * (ODC is also referred to as DirectIM and IM Image.) - * - * There are a few static helper functions at the top, then - * ODC stuff, then ft stuff. - * - * I feel like this is a good place to explain OFT, so I'm going to - * do just that. Each OFT packet has a header type. I guess this - * is pretty similar to the subtype of a SNAC packet. The type - * basically tells the other client the meaning of the OFT packet. - * There are two distinct types of file transfer, which I usually - * call "sendfile" and "getfile." Sendfile is when you send a file - * to another AIM user. Getfile is when you share a group of files, - * and other users request that you send them the files. - * - * A typical sendfile file transfer goes like this: - * 1) Sender sends a channel 2 ICBM telling the other user that - * we want to send them a file. At the same time, we open a - * listener socket (this should be done before sending the - * ICBM) on some port, and wait for them to connect to us. - * The ICBM we sent should contain our IP address and the port - * number that we're listening on. - * 2) The receiver connects to the sender on the given IP address - * and port. After the connection is established, the receiver - * sends an ICBM signifying that we are ready and waiting. - * 3) The sender sends an OFT PROMPT message over the OFT - * connection. - * 4) The receiver of the file sends back an exact copy of this - * OFT packet, except the cookie is filled in with the cookie - * from the ICBM. I think this might be an attempt to verify - * that the user that is connected is actually the guy that - * we sent the ICBM to. Oh, I've been calling this the ACK. - * 5) The sender starts sending raw data across the connection - * until the entire file has been sent. - * 6) The receiver knows the file is finished because the sender - * sent the file size in an earlier OFT packet. So then the - * receiver sends the DONE thingy (after filling in the - * "received" checksum and size) and closes the connection. + * Functions dealing with peer connections. This includes the code + * used to establish a peer connection for both Oscar File transfer + * (OFT) and Oscar Direct Connect (ODC). (ODC is also referred to + * as DirectIM and IM Image.) */ #ifdef HAVE_CONFIG_H #include <config.h> #endif +/* From the oscar PRPL */ #include "oscar.h" #include "peer.h" +/* From Gaim */ +#include "conversation.h" +#include "ft.h" +#include "network.h" +#include "notify.h" +#include "request.h" +#include "util.h" + #ifndef _WIN32 #include <stdio.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> -#include <sys/utsname.h> /* for aim_odc_initiate */ #include <arpa/inet.h> /* for inet_ntoa */ #include <limits.h> /* for UINT_MAX */ #endif @@ -94,1152 +68,929 @@ #define PF_INET6 PF_INET #endif -struct aim_odc_intdata { - guint8 cookie[8]; - char sn[MAXSNLEN+1]; - char ip[22]; -}; - -/** - * Convert the directory separator from / (0x2f) to ^A (0x01) - * - * @param name The filename to convert. - */ -static void -aim_oft_dirconvert_tostupid(char *name) -{ - while (name[0]) { - if (name[0] == 0x01) - name[0] = G_DIR_SEPARATOR; - name++; - } -} - -/** - * Convert the directory separator from ^A (0x01) to / (0x2f) - * - * @param name The filename to convert. - */ -static void -aim_oft_dirconvert_fromstupid(char *name) -{ - while (name[0]) { - if (name[0] == G_DIR_SEPARATOR) - name[0] = 0x01; - name++; - } -} - -/** - * Calculate oft checksum of buffer - * - * Prevcheck should be 0xFFFF0000 when starting a checksum of a file. The - * checksum is kind of a rolling checksum thing, so each time you get bytes - * of a file you just call this puppy and it updates the checksum. You can - * calculate the checksum of an entire file by calling this in a while or a - * for loop, or something. - * - * Thanks to Graham Booker for providing this improved checksum routine, - * which is simpler and should be more accurate than Josh Myer's original - * code. -- wtm - * - * This algorithm works every time I have tried it. The other fails - * sometimes. So, AOL who thought this up? It has got to be the weirdest - * checksum I have ever seen. - * - * @param buffer Buffer of data to checksum. Man I'd like to buff her... - * @param bufsize Size of buffer. - * @param prevcheck Previous checksum. - */ -guint32 -aim_oft_checksum_chunk(const guint8 *buffer, int bufferlen, guint32 prevcheck) -{ - guint32 check = (prevcheck >> 16) & 0xffff, oldcheck; - int i; - unsigned short val; - - for (i=0; i<bufferlen; i++) { - oldcheck = check; - if (i&1) - val = buffer[i]; - else - val = buffer[i] << 8; - check -= val; - /* - * The following appears to be necessary.... It happens - * every once in a while and the checksum doesn't fail. - */ - if (check > oldcheck) - check--; - } - check = ((check & 0x0000ffff) + (check >> 16)); - check = ((check & 0x0000ffff) + (check >> 16)); - return check << 16; -} - -guint32 -aim_oft_checksum_file(char *filename) -{ - FILE *fd; - guint32 checksum = 0xffff0000; - - if ((fd = fopen(filename, "rb"))) { - int bytes; - guint8 buffer[1024]; - - while ((bytes = fread(buffer, 1, 1024, fd))) - checksum = aim_oft_checksum_chunk(buffer, bytes, checksum); - fclose(fd); - } - - return checksum; -} - -/** - * After establishing a listening socket, this is called to accept a connection. It - * clones the conn used by the listener, and passes both of these to a signal handler. - * The signal handler should close the listener conn and keep track of the new conn, - * since this is what is used for file transfers and what not. - * - * @param sess The session. - * @param cur The conn the incoming connection is on. - * @return Return 0 if no errors, otherwise return the error number. - */ -int -aim_handlerendconnect(OscarSession *sess, OscarConnection *cur) -{ - int acceptfd = 0; - struct sockaddr addr; - socklen_t addrlen = sizeof(addr); - int ret = 0; - OscarConnection *newconn; - char ip[20]; - unsigned short port; - - if ((acceptfd = accept(cur->fd, &addr, &addrlen)) == -1) - return 0; /* not an error */ - - if ((addr.sa_family != PF_INET) && (addr.sa_family != PF_INET6)) { - close(acceptfd); - aim_conn_close(sess, cur); - return -1; - } - - strncpy(ip, inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr), sizeof(ip)); - port = ntohs(((struct sockaddr_in *)&addr)->sin_port); - - if (!(newconn = aim_cloneconn(sess, cur))) { - close(acceptfd); - aim_conn_close(sess, cur); - return -ENOMEM; - } - - newconn->type = AIM_CONN_TYPE_RENDEZVOUS; - newconn->fd = acceptfd; - - if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { - aim_rxcallback_t userfunc; - struct aim_odc_intdata *priv; - - priv = (struct aim_odc_intdata *)(newconn->internal = cur->internal); - cur->internal = NULL; - snprintf(priv->ip, sizeof(priv->ip), "%s:%hu", ip, port); - - if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIM_ESTABLISHED))) - ret = userfunc(sess, NULL, newconn, cur); - - } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { - } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) { - aim_rxcallback_t userfunc; - - if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, PEER_TYPE_ESTABLISHED))) - ret = userfunc(sess, NULL, newconn, cur); - - } else { - gaim_debug_warning("oscar", "Got a connection on a listener that's not rendezvous. Closing connection.\n"); - aim_conn_close(sess, newconn); - ret = -1; - } - - return ret; -} - -/** - * Send client-to-client typing notification over an established direct connection. - * - * @param sess The session. - * @param conn The already-connected ODC connection. - * @param typing If 0x0002, sends a "typing" message, 0x0001 sends "typed," and - * 0x0000 sends "stopped." - * @return Return 0 if no errors, otherwise return the error number. - */ -int -aim_odc_send_typing(OscarSession *sess, OscarConnection *conn, int typing) -{ - struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal; - FlapFrame *fr; - ByteStream *hdrbs; - guint8 *hdr; - int hdrlen = 0x44; - - if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) - return -EINVAL; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0001, 0))) - return -ENOMEM; - memcpy(fr->hdr.rend.magic, "ODC2", 4); - fr->hdr.rend.hdrlen = hdrlen + 8; - - if (!(hdr = calloc(1, hdrlen))) { - aim_frame_destroy(fr); - return -ENOMEM; - } - - hdrbs = &(fr->data); - aim_bstream_init(hdrbs, hdr, hdrlen); - - aimbs_put16(hdrbs, 0x0006); - aimbs_put16(hdrbs, 0x0000); - aimbs_putraw(hdrbs, intdata->cookie, 8); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put32(hdrbs, 0x00000000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - - if (typing == 0x0002) - aimbs_put16(hdrbs, 0x0002 | 0x0008); - else if (typing == 0x0001) - aimbs_put16(hdrbs, 0x0002 | 0x0004); - else - aimbs_put16(hdrbs, 0x0002); - - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_putstr(hdrbs, sess->sn); - - aim_bstream_setpos(hdrbs, 52); /* bleeehh */ - - aimbs_put8(hdrbs, 0x00); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put8(hdrbs, 0x00); - - /* end of hdr */ - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/** - * Send client-to-client IM over an established direct connection. - * Call this just like you would aim_send_im, to send a directim. - * - * @param sess The session. - * @param conn The already-connected ODC connection. - * @param msg Null-terminated string to send. - * @param len The length of the message to send, including binary data. - * @param encoding See the AIM_CHARSET_* defines in oscar.h - * @param isawaymsg 0 if this is not an auto-response, 1 if it is. - * @return Return 0 if no errors, otherwise return the error number. - */ -int -aim_odc_send_im(OscarSession *sess, OscarConnection *conn, const char *msg, int len, int encoding, int isawaymsg) -{ - FlapFrame *fr; - ByteStream *hdrbs; - struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal; - int hdrlen = 0x44; - guint8 *hdr; - - if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !msg) - return -EINVAL; - - if (!(fr = flap_frame_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, 0))) - return -ENOMEM; - - memcpy(fr->hdr.rend.magic, "ODC2", 4); - fr->hdr.rend.hdrlen = hdrlen + 8; - - if (!(hdr = calloc(1, hdrlen + len))) { - aim_frame_destroy(fr); - return -ENOMEM; - } - - hdrbs = &(fr->data); - aim_bstream_init(hdrbs, hdr, hdrlen + len); - - aimbs_put16(hdrbs, 0x0006); - aimbs_put16(hdrbs, 0x0000); - aimbs_putraw(hdrbs, intdata->cookie, 8); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put32(hdrbs, len); - aimbs_put16(hdrbs, encoding); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - - /* flags - used for typing notification and to mark if this is an away message */ - aimbs_put16(hdrbs, 0x0000 | isawaymsg); - - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_putstr(hdrbs, sess->sn); - - aim_bstream_setpos(hdrbs, 52); /* bleeehh */ - - aimbs_put8(hdrbs, 0x00); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x0000); - aimbs_put8(hdrbs, 0x00); - - /* end of hdr2 */ - -#if 0 /* XXX - this is how you send buddy icon info... */ - aimbs_put16(hdrbs, 0x0008); - aimbs_put16(hdrbs, 0x000c); - aimbs_put16(hdrbs, 0x0000); - aimbs_put16(hdrbs, 0x1466); - aimbs_put16(hdrbs, 0x0001); - aimbs_put16(hdrbs, 0x2e0f); - aimbs_put16(hdrbs, 0x393e); - aimbs_put16(hdrbs, 0xcac8); -#endif - aimbs_putraw(hdrbs, (guchar *)msg, len); - - aim_tx_enqueue(sess, fr); - - return 0; -} - -/** - * Get the screen name of the peer of a direct connection. - * - * @param conn The ODC connection. - * @return The screen name of the dude, or NULL if there was an anomaly. - */ -const char * -aim_odc_getsn(OscarConnection *conn) -{ - struct aim_odc_intdata *intdata; - - if (!conn || !conn->internal) - return NULL; - - if ((conn->type != AIM_CONN_TYPE_RENDEZVOUS) || - (conn->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM)) - return NULL; - - intdata = (struct aim_odc_intdata *)conn->internal; - - return intdata->sn; -} - -/** - * Get the cookie of a direct connection. - * - * @param conn The ODC connection. - * @return The cookie, an 8 byte unterminated string, or NULL if there was an anomaly. - */ -const guchar * -aim_odc_getcookie(OscarConnection *conn) -{ - struct aim_odc_intdata *intdata; - - if (!conn || !conn->internal) - return NULL; - - intdata = (struct aim_odc_intdata *)conn->internal; - - return intdata->cookie; -} - -/** - * Find the conn of a direct connection with the given buddy. - * - * @param sess The session. - * @param sn The screen name of the buddy whose direct connection you want to find. - * @return The conn for the direct connection with the given buddy, or NULL if no - * connection was found. - */ -OscarConnection * -aim_odc_getconn(OscarSession *sess, const char *sn) +PeerConnection * +peer_connection_find_by_type(OscarData *od, const char *sn, OscarCapability type) { GList *cur; - struct aim_odc_intdata *intdata; + PeerConnection *conn; - if (!sess || !sn || !strlen(sn)) - return NULL; - - for (cur = sess->oscar_connections; cur; cur = cur->next) + for (cur = od->peer_connections; cur != NULL; cur = cur->next) { - OscarConnection *conn; conn = cur->data; - if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) && (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)) { - intdata = conn->internal; - if (!aim_sncmp(intdata->sn, sn)) - return conn; - } + if ((conn->type == type) && !aim_sncmp(conn->sn, sn)) + return conn; } return NULL; } /** - * For those times when we want to open up the direct connection channel ourselves. - * - * You'll want to set up some kind of watcher on this socket. - * When the state changes, call aim_handlerendconnection with - * the connection returned by this. aim_handlerendconnection - * will accept the pending connection and stop listening. - * - * @param sess The session - * @param sn The screen name to connect to. - * @return The new connection. + * @param cookie This must be exactly 8 characters. */ -OscarConnection * -aim_odc_initiate(OscarSession *sess, const char *sn, int listenfd, - const guint8 *localip, guint16 port, const guint8 *mycookie) +PeerConnection * +peer_connection_find_by_cookie(OscarData *od, const char *sn, const guchar *cookie) +{ + GList *cur; + PeerConnection *conn; + + for (cur = od->peer_connections; cur != NULL; cur = cur->next) + { + conn = cur->data; + if (!memcmp(conn->cookie, cookie, 8) && !aim_sncmp(conn->sn, sn)) + return conn; + } + + return NULL; +} + +PeerConnection * +peer_connection_new(OscarData *od, OscarCapability type, const char *sn) { - OscarConnection *newconn; - IcbmCookie *cookie; - struct aim_odc_intdata *priv; - guint8 ck[8]; + PeerConnection *conn; + GaimAccount *account; + + account = gaim_connection_get_account(od->gc); + + conn = g_new0(PeerConnection, 1); + conn->od = od; + conn->type = type; + conn->sn = g_strdup(sn); + conn->buffer_outgoing = gaim_circ_buffer_new(0); + conn->listenerfd = -1; + conn->fd = -1; + conn->lastactivity = time(NULL); + conn->use_proxy |= gaim_account_get_bool(account, "use_rv_proxy", FALSE); - if (!localip) - return NULL; + if (type == OSCAR_CAPABILITY_DIRECTIM) + memcpy(conn->magic, "ODC2", 4); + else if (type == OSCAR_CAPABILITY_SENDFILE) + memcpy(conn->magic, "OFT2", 4); + + od->peer_connections = g_list_prepend(od->peer_connections, conn); + + return conn; +} + +static void +peer_connection_close(PeerConnection *conn) +{ + if (conn->type == OSCAR_CAPABILITY_DIRECTIM) + peer_odc_close(conn); + else if (conn->type == OSCAR_CAPABILITY_SENDFILE) + peer_oft_close(conn); - if (mycookie) { - memcpy(ck, mycookie, 8); - aim_im_sendch2_odcrequest(sess, ck, TRUE, sn, localip, port); - } else - aim_im_sendch2_odcrequest(sess, ck, FALSE, sn, localip, port); + if (conn->watcher_incoming != 0) + { + gaim_input_remove(conn->watcher_incoming); + conn->watcher_incoming = 0; + } + if (conn->watcher_outgoing != 0) + { + gaim_input_remove(conn->watcher_outgoing); + conn->watcher_outgoing = 0; + } + if (conn->listenerfd != -1) + { + close(conn->listenerfd); + conn->listenerfd = -1; + } + if (conn->fd != -1) + { + close(conn->fd); + conn->fd = -1; + } - cookie = (IcbmCookie *)calloc(1, sizeof(IcbmCookie)); - memcpy(cookie->cookie, ck, 8); - cookie->type = AIM_COOKIETYPE_OFTIM; + g_free(conn->buffer_incoming.data); + conn->buffer_incoming.data = NULL; + conn->buffer_incoming.len = 0; + conn->buffer_incoming.offset = 0; + + gaim_circ_buffer_destroy(conn->buffer_outgoing); + conn->buffer_outgoing = gaim_circ_buffer_new(0); - /* this one is for the cookie */ - priv = (struct aim_odc_intdata *)calloc(1, sizeof(struct aim_odc_intdata)); + conn->flags &= ~PEER_CONNECTION_FLAG_IS_INCOMING; +} + +static gboolean +peer_connection_destroy_cb(gpointer data) +{ + PeerConnection *conn; + + conn = data; + + gaim_request_close_with_handle(conn); + + peer_connection_close(conn); - memcpy(priv->cookie, ck, 8); - strncpy(priv->sn, sn, sizeof(priv->sn)); - cookie->data = priv; - aim_cachecookie(sess, cookie); - - /* XXX - switch to aim_cloneconn()? */ - if (!(newconn = oscar_connection_new(sess, AIM_CONN_TYPE_LISTENER))) { - close(listenfd); - return NULL; + if (conn->xfer != NULL) + { + GaimXferStatusType status; + conn->xfer->data = NULL; + status = gaim_xfer_get_status(conn->xfer); + if ((status != GAIM_XFER_STATUS_DONE) && + (status != GAIM_XFER_STATUS_CANCEL_LOCAL) && + (status != GAIM_XFER_STATUS_CANCEL_REMOTE)) + { + if ((conn->disconnect_reason == PEER_DISCONNECT_REMOTE_CLOSED) || + (conn->disconnect_reason == PEER_DISCONNECT_REMOTE_REFUSED)) + gaim_xfer_cancel_remote(conn->xfer); + else + gaim_xfer_cancel_local(conn->xfer); + } + gaim_xfer_unref(conn->xfer); + conn->xfer = NULL; } - /* this one is for the conn */ - priv = (struct aim_odc_intdata *)calloc(1, sizeof(struct aim_odc_intdata)); + g_free(conn->proxyip); + g_free(conn->clientip); + g_free(conn->verifiedip); + gaim_circ_buffer_destroy(conn->buffer_outgoing); - memcpy(priv->cookie, ck, 8); - strncpy(priv->sn, sn, sizeof(priv->sn)); + conn->od->peer_connections = g_list_remove(conn->od->peer_connections, conn); + + g_free(conn); + + return FALSE; +} - newconn->fd = listenfd; - newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; - newconn->internal = priv; - newconn->lastactivity = time(NULL); +void +peer_connection_destroy(PeerConnection *conn, PeerDisconnectReason reason) +{ + conn->disconnect_reason = reason; + if (conn->destroy_timeout != 0) + gaim_timeout_remove(conn->destroy_timeout); + peer_connection_destroy_cb(conn); +} - return newconn; +void +peer_connection_schedule_destroy(PeerConnection *conn, PeerDisconnectReason reason) +{ + if (conn->destroy_timeout != 0) + /* Already taken care of */ + return; + + gaim_debug_info("oscar", "Scheduling destruction of peer connection\n"); + conn->disconnect_reason = reason; + conn->destroy_timeout = gaim_timeout_add(0, peer_connection_destroy_cb, conn); } +/*******************************************************************/ +/* Begin code for receiving data on a peer connection */ +/*******************************************************************/ + /** - * Connect directly to the given buddy for directim. - * - * This is a wrapper for oscar_connection_new. - * - * If addr is NULL, the socket is not created, but the connection is - * allocated and setup to connect. + * This should be used to read ODC and OFT framing info. It should + * NOT be used to read the payload sent across the connection (IMs, + * file data, etc), and it should NOT be used to read proxy negotiation + * headers. * - * @param sess The Godly session. - * @param sn The screen name we're connecting to. I hope it's a girl... - * @param addr Address to connect to. - * @return The new connection. + * Unlike flap_connection_recv_cb(), this only reads one frame at a + * time. This is done so that the watcher can be changed during the + * handling of the frame. If the watcher is changed then this + * function will not read in any more data. This happens when + * reading the payload of a direct IM frame, or when we're + * receiving a file from the remote user. Once the data has been + * read, the watcher will be switched back to this function to + * continue reading the next frame. */ -OscarConnection * -aim_odc_connect(OscarSession *sess, const char *sn, const char *addr, const guint8 *cookie) +void +peer_connection_recv_cb(gpointer data, gint source, GaimInputCondition cond) { - OscarConnection *newconn; - struct aim_odc_intdata *intdata; + PeerConnection *conn; + ssize_t read; + guint8 header[6]; + + conn = data; + + /* Start reading a new ODC/OFT frame */ + if (conn->buffer_incoming.data == NULL) + { + /* Peek at the first 6 bytes to get the length */ + read = recv(conn->fd, &header, 6, MSG_PEEK); - if (!sess || !sn) - return NULL; + /* Check if the remote user closed the connection */ + if (read == 0) + { + peer_connection_destroy(conn, PEER_DISCONNECT_REMOTE_CLOSED); + return; + } + + /* If there was an error then close the connection */ + if (read == -1) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No worries */ + return; - if (!(intdata = calloc(1, sizeof(struct aim_odc_intdata)))) - return NULL; - memcpy(intdata->cookie, cookie, 8); - strncpy(intdata->sn, sn, sizeof(intdata->sn)); - if (addr) - strncpy(intdata->ip, addr, sizeof(intdata->ip)); + peer_connection_destroy(conn, PEER_DISCONNECT_LOST_CONNECTION); + return; + } + + conn->lastactivity = time(NULL); + + /* If we don't even have the first 6 bytes then do nothing */ + if (read < 6) + return; + + /* Read the first 6 bytes (magic string and frame length) */ + read = recv(conn->fd, &header, 6, 0); - /* XXX - verify that non-blocking connects actually work */ - if (!(newconn = oscar_connection_new(sess, AIM_CONN_TYPE_RENDEZVOUS))) { - free(intdata); - return NULL; + /* All ODC/OFT frames must start with a magic string */ + if (memcmp(conn->magic, header, 4)) + { + gaim_debug_warning("oscar", "Expecting magic string to " + "be %c%c%c%c but received magic string %c%c%c%c. " + "Closing connection.\n", + conn->magic[0], conn->magic[1], conn->magic[2], + conn->magic[3], header[0], header[1], header[2], header[3]); + peer_connection_destroy(conn, PEER_DISCONNECT_INVALID_DATA); + return; + } + + /* Initialize a new temporary ByteStream for incoming data */ + conn->buffer_incoming.len = aimutil_get16(&header[4]) - 6; + conn->buffer_incoming.data = g_new(guint8, conn->buffer_incoming.len); + conn->buffer_incoming.offset = 0; } - newconn->internal = intdata; - newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; + /* Read data into the temporary buffer until it is complete */ + read = recv(conn->fd, + &conn->buffer_incoming.data[conn->buffer_incoming.offset], + conn->buffer_incoming.len - conn->buffer_incoming.offset, + 0); + + /* Check if the remote user closed the connection */ + if (read == 0) + { + peer_connection_destroy(conn, PEER_DISCONNECT_REMOTE_CLOSED); + return; + } + + if (read == -1) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No worries */ + return; + + peer_connection_destroy(conn, PEER_DISCONNECT_LOST_CONNECTION); + return; + } + + conn->lastactivity = time(NULL); + conn->buffer_incoming.offset += read; + if (conn->buffer_incoming.offset < conn->buffer_incoming.len) + /* Waiting for more data to arrive */ + return; + + /* We have a complete ODC/OFT frame! Handle it and continue reading */ + byte_stream_rewind(&conn->buffer_incoming); + if (conn->type == OSCAR_CAPABILITY_DIRECTIM) + { + peer_odc_recv_frame(conn, &conn->buffer_incoming); + } + else if (conn->type == OSCAR_CAPABILITY_SENDFILE) + { + peer_oft_recv_frame(conn, &conn->buffer_incoming); + } + g_free(conn->buffer_incoming.data); + conn->buffer_incoming.data = NULL; +} - return newconn; +/*******************************************************************/ +/* End code for receiving data on a peer connection */ +/*******************************************************************/ + +/*******************************************************************/ +/* Begin code for sending data on a peer connection */ +/*******************************************************************/ + +static void +send_cb(gpointer data, gint source, GaimInputCondition cond) +{ + PeerConnection *conn; + gsize writelen; + ssize_t wrotelen; + + conn = data; + writelen = gaim_circ_buffer_get_max_read(conn->buffer_outgoing); + + if (writelen == 0) + { + gaim_input_remove(conn->watcher_outgoing); + conn->watcher_outgoing = 0; + return; + } + + wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); + if (wrotelen <= 0) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No worries */ + return; + + if (conn->ready) + peer_connection_schedule_destroy(conn, PEER_DISCONNECT_LOST_CONNECTION); + else + { + /* + * This could happen when unable to send a negotiation + * frame to a peer proxy server. + */ + peer_connection_trynext(conn); + } + return; + } + + gaim_circ_buffer_mark_read(conn->buffer_outgoing, wrotelen); + conn->lastactivity = time(NULL); } /** - * Sometimes you just don't know with these kinds of people. - * - * @param sess The session. - * @param conn The ODC connection of the incoming data. - * @param frr The frame allocated for the incoming data. - * @param bs It stands for "bologna sandwich." - * @return Return 0 if no errors, otherwise return the error number. + * This should be called by OFT/ODC code to send a standard OFT or ODC + * frame across the peer connection along with some payload data. Or + * maybe a file. Anything, really. */ -static int -handlehdr_odc(OscarSession *sess, OscarConnection *conn, FlapFrame *frr, ByteStream *bs) +void +peer_connection_send(PeerConnection *conn, ByteStream *bs) { - FlapFrame fr; - int ret = 0; - aim_rxcallback_t userfunc; - guint32 payloadlength; - guint16 flags, encoding; - char *snptr = NULL; + /* Add everything to our outgoing buffer */ + gaim_circ_buffer_append(conn->buffer_outgoing, bs->data, bs->len); - fr.conn = conn; + /* If we haven't already started writing stuff, then start the cycle */ + if (conn->watcher_outgoing == 0) + { + conn->watcher_outgoing = gaim_input_add(conn->fd, + GAIM_INPUT_WRITE, send_cb, conn); + send_cb(conn, conn->fd, 0); + } +} + +/*******************************************************************/ +/* End code for sending data on a peer connection */ +/*******************************************************************/ - /* AAA - ugly */ - aim_bstream_setpos(bs, 20); - payloadlength = aimbs_get32(bs); +/*******************************************************************/ +/* Begin code for establishing a peer connection */ +/*******************************************************************/ - aim_bstream_setpos(bs, 24); - encoding = aimbs_get16(bs); - - aim_bstream_setpos(bs, 30); - flags = aimbs_get16(bs); +void +peer_connection_finalize_connection(PeerConnection *conn) +{ + conn->watcher_incoming = gaim_input_add(conn->fd, + GAIM_INPUT_READ, peer_connection_recv_cb, conn); - aim_bstream_setpos(bs, 36); - /* XXX - create an aimbs_getnullstr function? */ - snptr = aimbs_getstr(bs, 32); /* Next 32 bytes contain the sn, padded with null chars */ - - gaim_debug_misc("oscar", "faim: OFT frame: handlehdr_odc: %04x / %04x / %s\n", payloadlength, flags, snptr); - - if (flags & 0x0008) { - if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMTYPING))) - ret = userfunc(sess, &fr, snptr, 2); - } else if (flags & 0x0004) { - if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMTYPING))) - ret = userfunc(sess, &fr, snptr, 1); - } else { - if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMTYPING))) - ret = userfunc(sess, &fr, snptr, 0); + if (conn->type == OSCAR_CAPABILITY_DIRECTIM) + { + /* + * If we are connecting to them then send our cookie so they + * can verify who we are. Note: This doesn't seem to be + * necessary, but it also doesn't seem to hurt. + */ + if (!(conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING)) + peer_odc_send_cookie(conn); + } + else if (conn->type == OSCAR_CAPABILITY_SENDFILE) + { + if (gaim_xfer_get_type(conn->xfer) == GAIM_XFER_SEND) + { + peer_oft_send_prompt(conn); + } } - if ((payloadlength != 0) && (payloadlength != UINT_MAX)) { - char *msg; - int recvd = 0; - int i, isawaymsg; - - isawaymsg = flags & 0x0001; - - if (!(msg = calloc(1, payloadlength+1))) { - free(snptr); - return -ENOMEM; - } - - while (payloadlength - recvd) { - if (payloadlength - recvd >= 1024) - i = aim_recv(conn->fd, &msg[recvd], 1024); - else - i = aim_recv(conn->fd, &msg[recvd], payloadlength - recvd); - if (i <= 0) { - free(msg); - free(snptr); - return -1; - } - recvd = recvd + i; - if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER))) - ret = userfunc(sess, &fr, snptr, (double)recvd / payloadlength); - } - - if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMINCOMING))) - ret = userfunc(sess, &fr, snptr, msg, payloadlength, encoding, isawaymsg); - - free(msg); - } - - free(snptr); - - return ret; -} - -PeerConnection * -aim_oft_createinfo(OscarSession *sess, const guint8 *cookie, const char *sn, const char *ip, guint16 port, guint32 size, guint32 modtime, char *filename, int send_or_recv, int method, int stage) -{ - PeerConnection *new; - - if (!sess) - return NULL; - - if (!(new = (PeerConnection *)calloc(1, sizeof(PeerConnection)))) - return NULL; - - new->sess = sess; - if (cookie) - memcpy(new->cookie, cookie, 8); - else - aim_icbm_makecookie(new->cookie); - if (ip) - new->clientip = strdup(ip); - else - new->clientip = NULL; - if (sn) - new->sn = strdup(sn); - else - new->sn = NULL; - new->method = method; - new->send_or_recv = send_or_recv; - new->stage = stage; - new->port = port; - new->xfer_reffed = FALSE; - new->success = FALSE; - new->fh.totfiles = 1; - new->fh.filesleft = 1; - new->fh.totparts = 1; - new->fh.partsleft = 1; - new->fh.totsize = size; - new->fh.size = size; - new->fh.modtime = modtime; - new->fh.checksum = 0xffff0000; - new->fh.rfrcsum = 0xffff0000; - new->fh.rfcsum = 0xffff0000; - new->fh.recvcsum = 0xffff0000; - strncpy(new->fh.idstring, "OFT_Windows ICBMFT V1.1 32", 31); - if (filename) { - strncpy(new->fh.name, filename, 63); - new->fh.name[63] = '\0'; - } - - sess->peer_connections = g_list_prepend(sess->peer_connections, new); - - return new; -} - -PeerProxyInfo *aim_rv_proxy_createinfo(OscarSession *sess, const guint8 *cookie, - guint16 port) -{ - PeerProxyInfo *proxy_info; - - if (!(proxy_info = (PeerProxyInfo*)calloc(1, sizeof(PeerProxyInfo)))) - return NULL; - - proxy_info->sess = sess; - proxy_info->port = port; - proxy_info->packet_ver = AIM_RV_PROXY_PACKETVER_DFLT; - proxy_info->unknownA = AIM_RV_PROXY_UNKNOWNA_DFLT; - - if (cookie) - memcpy(proxy_info->cookie, cookie, 8); - - return proxy_info; + /* + * Tell the remote user that we're connected (which may also imply + * that we've accepted their request). + */ + if (!(conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING)) + aim_im_sendch2_connected(conn); } /** - * Remove the given PeerConnection from the PeerConnection linked list, and - * then free its memory. - * - * @param sess The session. - * @param peer_connection The PeerConnection that we're destroying. - * @return Return 0 if no errors, otherwise return the error number. + * We tried to make an outgoing connection to a remote user. It + * either connected or failed to connect. */ -int -aim_oft_destroyinfo(PeerConnection *peer_connection) +static void +peer_connection_established_cb(gpointer data, gint source, GaimInputCondition cond) { - OscarSession *sess; - - if (!peer_connection || !(sess = peer_connection->sess)) - return -EINVAL; - - sess->peer_connections = g_list_remove(sess->peer_connections, peer_connection); - - free(peer_connection->sn); - free(peer_connection->proxyip); - free(peer_connection->clientip); - free(peer_connection->verifiedip); - free(peer_connection); + NewPeerConnectionData *new_conn_data; + GaimConnection *gc; + PeerConnection *conn; - return 0; -} + new_conn_data = data; + gc = new_conn_data->gc; + conn = new_conn_data->conn; + g_free(new_conn_data); -/** - * Creates a listener socket so the other dude can connect to us. - * - * You'll want to set up some kind of watcher on this socket. - * When the state changes, call aim_handlerendconnection with - * the connection returned by this. aim_handlerendconnection - * will accept the pending connection and stop listening. - * - * @param sess The session. - * @param peer_connection File transfer information associated with this - * connection. - * @return Return 0 if no errors, otherwise return the error number. - */ -int -aim_sendfile_listen(OscarSession *sess, PeerConnection *peer_connection, int listenfd) -{ - if (!peer_connection) - return -EINVAL; - - if (!(peer_connection->conn = oscar_connection_new(sess, AIM_CONN_TYPE_LISTENER))) { - close(listenfd); - return -ENOMEM; + if (!g_list_find(gaim_connections_get_all(), gc)) + { + if (source >= 0) + close(source); + return; } - peer_connection->conn->fd = listenfd; - peer_connection->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; - peer_connection->conn->lastactivity = time(NULL); - - return 0; -} - -/** - * Extract an &aim_fileheader_t from the given buffer. - * - * @param bs The should be from an incoming rendezvous packet. - * @return A pointer to new struct on success, or NULL on error. - */ -static PeerFrame * -aim_oft_getheader(ByteStream *bs) -{ - PeerFrame *fh; - - if (!(fh = calloc(1, sizeof(PeerFrame)))) - return NULL; + if (source < 0) + { + peer_connection_trynext(conn); + return; + } - /* The bstream should be positioned after the hdrtype. */ - aimbs_getrawbuf(bs, fh->bcookie, 8); - fh->encrypt = aimbs_get16(bs); - fh->compress = aimbs_get16(bs); - fh->totfiles = aimbs_get16(bs); - fh->filesleft = aimbs_get16(bs); - fh->totparts = aimbs_get16(bs); - fh->partsleft = aimbs_get16(bs); - fh->totsize = aimbs_get32(bs); - fh->size = aimbs_get32(bs); - fh->modtime = aimbs_get32(bs); - fh->checksum = aimbs_get32(bs); - fh->rfrcsum = aimbs_get32(bs); - fh->rfsize = aimbs_get32(bs); - fh->cretime = aimbs_get32(bs); - fh->rfcsum = aimbs_get32(bs); - fh->nrecvd = aimbs_get32(bs); - fh->recvcsum = aimbs_get32(bs); - aimbs_getrawbuf(bs, (guchar *)fh->idstring, 32); - fh->flags = aimbs_get8(bs); - fh->lnameoffset = aimbs_get8(bs); - fh->lsizeoffset = aimbs_get8(bs); - aimbs_getrawbuf(bs, (guchar *)fh->dummy, 69); - aimbs_getrawbuf(bs, (guchar *)fh->macfileinfo, 16); - fh->nencode = aimbs_get16(bs); - fh->nlanguage = aimbs_get16(bs); - aimbs_getrawbuf(bs, (guchar *)fh->name, 64); /* XXX - filenames longer than 64B */ - fh->name[63] = '\0'; + conn->fd = source; - return fh; + peer_connection_finalize_connection(conn); } /** - * Fills a buffer with network-order fh data + * This is the watcher callback for any listening socket that is + * waiting for a peer to connect. When a peer connects we set the + * input watcher to start reading data from the peer. * - * @param bs A bstream to fill -- automatically initialized - * @param fh A PeerFrame to get data from. - * @return Return non-zero on error. + * To make sure that the connection is with the intended person and + * not with a malicious middle man, we don't send anything until we've + * received a peer frame from the remote user and have verified that + * the cookie in the peer frame matches the cookie that was exchanged + * in the channel 2 ICBM. */ -static int -aim_oft_buildheader(ByteStream *bs, PeerFrame *fh) +void +peer_connection_listen_cb(gpointer data, gint source, GaimInputCondition cond) { - guint8 *hdr; + PeerConnection *conn; + OscarData *od; + GaimConnection *gc; + GaimAccount *account; + struct sockaddr addr; + socklen_t addrlen = sizeof(addr); - if (!bs || !fh) - return -EINVAL; - - if (!(hdr = (unsigned char *)calloc(1, 0x100 - 8))) - return -ENOMEM; + conn = data; + od = conn->od; + gc = od->gc; + account = gaim_connection_get_account(gc); - aim_bstream_init(bs, hdr, 0x100 - 8); - aimbs_putraw(bs, fh->bcookie, 8); - aimbs_put16(bs, fh->encrypt); - aimbs_put16(bs, fh->compress); - aimbs_put16(bs, fh->totfiles); - aimbs_put16(bs, fh->filesleft); - aimbs_put16(bs, fh->totparts); - aimbs_put16(bs, fh->partsleft); - aimbs_put32(bs, fh->totsize); - aimbs_put32(bs, fh->size); - aimbs_put32(bs, fh->modtime); - aimbs_put32(bs, fh->checksum); - aimbs_put32(bs, fh->rfrcsum); - aimbs_put32(bs, fh->rfsize); - aimbs_put32(bs, fh->cretime); - aimbs_put32(bs, fh->rfcsum); - aimbs_put32(bs, fh->nrecvd); - aimbs_put32(bs, fh->recvcsum); - aimbs_putraw(bs, (guchar *)fh->idstring, 32); - aimbs_put8(bs, fh->flags); - aimbs_put8(bs, fh->lnameoffset); - aimbs_put8(bs, fh->lsizeoffset); - aimbs_putraw(bs, (guchar *)fh->dummy, 69); - aimbs_putraw(bs, (guchar *)fh->macfileinfo, 16); - aimbs_put16(bs, fh->nencode); - aimbs_put16(bs, fh->nlanguage); - aimbs_putraw(bs, (guchar *)fh->name, 64); /* XXX - filenames longer than 64B */ + gaim_debug_info("oscar", "Accepting connection on listener socket.\n"); + + conn->fd = accept(conn->listenerfd, &addr, &addrlen); + if (conn->fd == -1) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No connection yet--no worries */ + /* TODO: Hmm, but they SHOULD be connected if we're here, right? */ + return; - return 0; + peer_connection_trynext(conn); + return; + } + + if ((addr.sa_family != PF_INET) && (addr.sa_family != PF_INET6)) + { + /* Invalid connection type?! Continue waiting. */ + close(conn->fd); + return; + } + + fcntl(conn->fd, F_SETFL, O_NONBLOCK); + gaim_input_remove(conn->watcher_incoming); + + peer_connection_finalize_connection(conn); } /** - * Create an OFT packet based on the given information, and send it on its merry way. - * - * @param sess The session. - * @param type The subtype of the OFT packet we're sending. - * @param peer_connection The PeerConnection with the connection and OFT - * info we're sending. - * @return Return 0 if no errors, otherwise return the error number. + * We've just opened a listener socket, so we send the remote + * user an ICBM and ask them to connect to us. */ -int aim_oft_sendheader(OscarSession *sess, guint16 type, PeerConnection *peer_connection) +static void +peer_connection_establish_listener_cb(int listenerfd, gpointer data) { - FlapFrame *fr; - - if (!sess || !peer_connection || !peer_connection->conn || (peer_connection->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) - return -EINVAL; + NewPeerConnectionData *new_conn_data; + PeerConnection *conn; + OscarData *od; + GaimConnection *gc; + GaimAccount *account; + GaimConversation *conv; + char *tmp; + FlapConnection *bos_conn; + const char *listener_ip; + unsigned short listener_port; -#if 0 - /* - * If you are receiving a file, the cookie should be null, if you are sending a - * file, the cookie should be the same as the one used in the ICBM negotiation - * SNACs. - */ - fh->lnameoffset = 0x1a; - fh->lsizeoffset = 0x10; + new_conn_data = data; + gc = new_conn_data->gc; + conn = new_conn_data->conn; + g_free(new_conn_data); - /* These should be the same as charset and charsubset in ICBMs */ - fh->nencode = 0x0000; - fh->nlanguage = 0x0000; -#endif - - aim_oft_dirconvert_tostupid(peer_connection->fh.name); - - if (!(fr = flap_frame_new(sess, peer_connection->conn, AIM_FRAMETYPE_OFT, type, 0))) - return -ENOMEM; - - if (aim_oft_buildheader(&fr->data, &peer_connection->fh) == -1) { - aim_frame_destroy(fr); - return -ENOMEM; + if (!g_list_find(gaim_connections_get_all(), gc)) + { + if (listenerfd != -1) + close(listenerfd); + return; } - memcpy(fr->hdr.rend.magic, "OFT2", 4); - fr->hdr.rend.hdrlen = aim_bstream_curpos(&fr->data) + 8; + if (listenerfd == -1) + { + /* Could not open listener socket */ + peer_connection_trynext(conn); + return; + } + + od = conn->od; + account = gaim_connection_get_account(gc); + conn->listenerfd = listenerfd; - aim_tx_enqueue(sess, fr); + /* Send the "please connect to me!" ICBM */ + bos_conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM); + listener_ip = gaim_network_get_my_ip(bos_conn->fd); + listener_port = gaim_network_get_port_from_fd(conn->listenerfd); + if (conn->type == OSCAR_CAPABILITY_DIRECTIM) + { + aim_im_sendch2_odc_requestdirect(od, + conn->cookie, conn->sn, gaim_network_ip_atoi(listener_ip), + listener_port, ++conn->lastrequestnumber); - return 0; + /* Print a message to a local conversation window */ + conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, conn->sn); + tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for " + "Direct IM."), conn->sn, listener_ip, listener_port); + gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL)); + g_free(tmp); + } + else if (conn->type == OSCAR_CAPABILITY_SENDFILE) + { + aim_im_sendch2_sendfile_requestdirect(od, + conn->cookie, conn->sn, + gaim_network_ip_atoi(listener_ip), + listener_port, ++conn->lastrequestnumber, + (const gchar *)conn->xferdata.name, + conn->xferdata.size, conn->xferdata.totfiles); + } } /** - * Create a rendezvous "init recv" packet and send it on its merry way. - * This is the first packet sent to the proxy server by the second client - * involved in this rendezvous proxy session. - * - * @param sess The session. - * @param proxy_info Changable pieces of data for this packet - * @return Return 0 if no errors, otherwise return the error number. + * Try to establish the given PeerConnection using a defined + * sequence of steps. */ -int -aim_rv_proxy_init_recv(PeerProxyInfo *proxy_info) +void +peer_connection_trynext(PeerConnection *conn) { -#if 0 - aim_tlvlist_t *tlvlist_sendfile; -#endif - ByteStream bs; - guint8 *bs_raw; - guint16 packet_len; - guint8 sn_len; - int err; + NewPeerConnectionData *new_conn_data; + GaimAccount *account; - err = 0; + new_conn_data = g_new(NewPeerConnectionData, 1); + new_conn_data->gc = conn->od->gc; + new_conn_data->conn = conn; + + account = gaim_connection_get_account(new_conn_data->gc); - if (!proxy_info) - return -EINVAL; + /* + * Close any remnants of a previous failed connection attempt. + */ + peer_connection_close(conn); - sn_len = strlen(proxy_info->sess->sn); - packet_len = 2 + 2 /* packet_len, packet_ver */ - + 2 + 4 /* cmd_type, unknownA */ - + 2 /* flags */ - + 1 + sn_len /* Length/value pair for screenname */ - + 8 /* ICBM Cookie */ - + 2 /* port */ - + 2 + 2 + 16; /* TLV for Filesend capability block */ + /* + * 1. Attempt to connect to the remote user using their verifiedip. + */ + if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_VERIFIEDIP) && + (conn->verifiedip != NULL) && (conn->port != 0) && (!conn->use_proxy)) + { + conn->flags |= PEER_CONNECTION_FLAG_TRIED_VERIFIEDIP; - if (!(bs_raw = malloc(packet_len))) - return -ENOMEM; + if (conn->type == OSCAR_CAPABILITY_DIRECTIM) + { + gchar *tmp; + GaimConversation *conv; + tmp = g_strdup_printf(_("Attempting to connect to %s:%hu."), + conn->verifiedip, conn->port); + conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, conn->sn); + gaim_conversation_write(conv, NULL, tmp, + GAIM_MESSAGE_SYSTEM, time(NULL)); + g_free(tmp); + } - aim_bstream_init(&bs, bs_raw, packet_len); - aimbs_put16(&bs, packet_len - 2); /* Length includes only packets after length marker */ - aimbs_put16(&bs, proxy_info->packet_ver); - aimbs_put16(&bs, AIM_RV_PROXY_INIT_RECV); - aimbs_put32(&bs, proxy_info->unknownA); - aimbs_put16(&bs, proxy_info->flags); - aimbs_put8(&bs, sn_len); - aimbs_putraw(&bs, (const guchar *)proxy_info->sess->sn, sn_len); - aimbs_put16(&bs, proxy_info->port); - aimbs_putraw(&bs, proxy_info->cookie, 8); + if (gaim_proxy_connect(account, conn->verifiedip, conn->port, + peer_connection_established_cb, new_conn_data) == 0) + { + /* Connecting... */ + return; + } + } - aimbs_put16(&bs, 0x0001); /* Type */ - aimbs_put16(&bs, 16); /* Length */ - aimbs_putcaps(&bs, AIM_CAPS_SENDFILE); /* Value */ - + /* + * 2. Attempt to connect to the remote user using their clientip. + */ + if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_CLIENTIP) && + (conn->clientip != NULL) && (conn->port != 0) && (!conn->use_proxy)) + { + conn->flags |= PEER_CONNECTION_FLAG_TRIED_CLIENTIP; -#if 0 - /* TODO: Use built-in TLV */ - aim_tlvlist_add_caps(&tlvlist_sendfile, 0x0001, AIM_CAPS_SENDFILE); - aim_tlvlist_write(&bs, &tlvlist_sendfile); -#endif - - aim_bstream_rewind(&bs); - if (aim_bstream_send(&bs, proxy_info->conn, packet_len) != packet_len) - err = errno; - proxy_info->conn->lastactivity = time(NULL); - -#if 0 - aim_tlvlist_free(tlvlist_sendfile); -#endif - free(bs_raw); + if (strcmp(conn->verifiedip, conn->clientip)) + { + if (conn->type == OSCAR_CAPABILITY_DIRECTIM) + { + gchar *tmp; + GaimConversation *conv; + tmp = g_strdup_printf(_("Attempting to connect to %s:%hu."), + conn->clientip, conn->port); + conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, conn->sn); + gaim_conversation_write(conv, NULL, tmp, + GAIM_MESSAGE_SYSTEM, time(NULL)); + g_free(tmp); + } - return err; -} - + if (gaim_proxy_connect(account, conn->clientip, conn->port, + peer_connection_established_cb, new_conn_data) == 0) + { + /* Connecting... */ + return; + } + } + } -/** - * Create a rendezvous "init send" packet and send it on its merry way. - * This is the first packet sent to the proxy server by the client - * first indicating that this will be a proxied connection - * - * @param sess The session. - * @param proxy_info Changable pieces of data for this packet - * @return Return 0 if no errors, otherwise return the error number. - */ -int -aim_rv_proxy_init_send(PeerProxyInfo *proxy_info) -{ -#if 0 - aim_tlvlist_t *tlvlist_sendfile; -#endif - ByteStream bs; - guint8 *bs_raw; - guint16 packet_len; - guint8 sn_len; - int err; + /* + * 3. Attempt to have the remote user connect to us (using both + * our verifiedip and our clientip). + */ + if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_INCOMING) && + (!conn->use_proxy)) + { + conn->flags |= PEER_CONNECTION_FLAG_TRIED_INCOMING; - err = 0; + /* + * Remote user is connecting to us, so we'll need to verify + * that the user who connected is our friend. + */ + conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING; - if (!proxy_info) - return -EINVAL; + if (gaim_network_listen_range(5190, 5290, SOCK_STREAM, + peer_connection_establish_listener_cb, new_conn_data)) + { + /* Opening listener socket... */ + return; + } + } - sn_len = strlen(proxy_info->sess->sn); - packet_len = 2 + 2 /* packet_len, packet_ver */ - + 2 + 4 /* cmd_type, unknownA */ - + 2 /* flags */ - + 1 + sn_len /* Length/value pair for screenname */ - + 8 /* ICBM Cookie */ - + 2 + 2 + 16; /* TLV for Filesend capability block */ + /* + * 4. Attempt to have both users connect to an intermediate proxy + * server. + */ + if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_PROXY)) + { + conn->flags |= PEER_CONNECTION_FLAG_TRIED_PROXY; - if (!(bs_raw = malloc(packet_len))) - return -ENOMEM; - - aim_bstream_init(&bs, bs_raw, packet_len); - aimbs_put16(&bs, packet_len - 2); /* Length includes only packets after length marker */ - aimbs_put16(&bs, proxy_info->packet_ver); - aimbs_put16(&bs, AIM_RV_PROXY_INIT_SEND); - aimbs_put32(&bs, proxy_info->unknownA); - aimbs_put16(&bs, proxy_info->flags); - aimbs_put8(&bs, sn_len); - aimbs_putraw(&bs, (const guchar *)proxy_info->sess->sn, sn_len); - aimbs_putraw(&bs, proxy_info->cookie, 8); + /* + * If we initiate the proxy connection, then the remote user + * could be anyone, so we need to verify that the user who + * connected is our friend. + */ + if (!conn->use_proxy) + conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING; - aimbs_put16(&bs, 0x0001); /* Type */ - aimbs_put16(&bs, 16); /* Length */ - aimbs_putcaps(&bs, AIM_CAPS_SENDFILE); /* Value */ - - /* TODO: Use built-in TLV */ -#if 0 - aim_tlvlist_add_caps(&tlvlist_sendfile, 0x0001, AIM_CAPS_SENDFILE); - aim_tlvlist_write(&bs, &tlvlist_sendfile); -#endif + if (conn->type == OSCAR_CAPABILITY_DIRECTIM) + { + gchar *tmp; + GaimConversation *conv; + tmp = g_strdup_printf(_("Attempting to connect via proxy server.")); + conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, conn->sn); + gaim_conversation_write(conv, NULL, tmp, + GAIM_MESSAGE_SYSTEM, time(NULL)); + g_free(tmp); + } - aim_bstream_rewind(&bs); - if (aim_bstream_send(&bs, proxy_info->conn, packet_len) != packet_len) - err = errno; - proxy_info->conn->lastactivity = time(NULL); + if (gaim_proxy_connect(account, + (conn->proxyip != NULL) ? conn->proxyip : PEER_PROXY_SERVER, + PEER_PROXY_PORT, + peer_proxy_connection_established_cb, new_conn_data) == 0) + { + /* Connecting... */ + return; + } + } -#if 0 - aim_tlvlist_free(tlvlist_sendfile); -#endif - free(bs_raw); + g_free(new_conn_data); - return err; + /* Give up! */ + peer_connection_destroy(conn, PEER_DISCONNECT_COULD_NOT_CONNECT); } /** - * Handle incoming data on a rendezvous connection. This is analogous to the - * consumesnac function in rxhandlers.c, and I really think this should probably - * be in rxhandlers.c as well, but I haven't finished cleaning everything up yet. - * - * @param sess The session. - * @param fr The frame allocated for the incoming data. - * @return Return 0 if the packet was handled correctly, otherwise return the - * error number. + * Initiate a peer connection with someone. */ -int -aim_rxdispatch_rendezvous(OscarSession *sess, FlapFrame *fr) +void +peer_connection_propose(OscarData *od, OscarCapability type, const char *sn) { - OscarConnection *conn = fr->conn; - int ret = 1; + PeerConnection *conn; + GaimAccount *account; + + account = gaim_connection_get_account(od->gc); - if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { - if (fr->hdr.rend.type == 0x0001) - ret = handlehdr_odc(sess, conn, fr, &fr->data); - else - gaim_debug_info("oscar", "ODC directim frame unknown, type is %04x\n", fr->hdr.rend.type); + if (type == OSCAR_CAPABILITY_DIRECTIM) + { + conn = peer_connection_find_by_type(od, sn, type); + if (conn != NULL) + { + if (conn->ready) + { + GaimConversation *conv; - } else { - aim_rxcallback_t userfunc; - PeerFrame *header = aim_oft_getheader(&fr->data); - aim_oft_dirconvert_fromstupid(header->name); /* XXX - This should be client-side */ + gaim_debug_info("oscar", "Already have a direct IM " + "session with %s.\n", sn); + account = gaim_connection_get_account(od->gc); + conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, + sn, account); + if (conv != NULL) + gaim_conversation_present(conv); + return; + } - if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, fr->hdr.rend.type))) - ret = userfunc(sess, fr, conn, header->bcookie, header); - - free(header); + /* Cancel the old connection and try again */ + peer_connection_destroy(conn, PEER_DISCONNECT_RETRYING); + } } - if (ret == -1) - aim_conn_close(sess, conn); + conn = peer_connection_new(od, type, sn); + conn->flags |= PEER_CONNECTION_FLAG_INITIATED_BY_ME; + conn->flags |= PEER_CONNECTION_FLAG_APPROVED; + aim_icbm_makecookie(conn->cookie); + + peer_connection_trynext(conn); +} + +/** + * Someone else wants to establish a peer connection with us, + * and we said yes. + */ +static void +peer_connection_got_proposition_yes_cb(gpointer data, gint id) +{ + PeerConnection *conn; + + conn = data; - return ret; + conn->flags |= PEER_CONNECTION_FLAG_APPROVED; + peer_connection_trynext(conn); +} + +/** + * Someone else wants to establish a peer connection with us, + * and we said no. + * + * "Well, one time my friend asked me if I wanted to play the + * piccolo. But I said no." + */ +static void +peer_connection_got_proposition_no_cb(gpointer data, gint id) +{ + PeerConnection *conn; + + conn = data; + + aim_im_denytransfer(conn->od, conn->sn, conn->cookie, + AIM_TRANSFER_DENY_DECLINE); + peer_connection_destroy(conn, PEER_DISCONNECT_LOCAL_CLOSED); } /** - * Handle incoming data on a rendezvous proxy connection. This is similar to - * aim_rxdispatch_rendezvous above and should probably be kept with that function. - * - * @param sess The session. - * @param fr The frame allocated for the incoming data. - * @return Return 0 if the packet was handled correctly, otherwise return the - * error number. + * Someone else wants to establish a peer connection with us. */ -PeerProxyInfo * -aim_rv_proxy_read(OscarSession *sess, OscarConnection *conn) +void +peer_connection_got_proposition(OscarData *od, const gchar *sn, const gchar *message, IcbmArgsCh2 *args) { - ByteStream bs_hdr; - guint8 hdr_buf[AIM_RV_PROXY_HDR_LEN]; - ByteStream bs_body; /* The body (everything but the header) of the packet */ - guint8 *body_buf = NULL; - guint8 body_len; + GaimConnection *gc; + GaimAccount *account; + PeerConnection *conn; + gchar *buf; + + gc = od->gc; + account = gaim_connection_get_account(gc); - char str_ip[30] = {""}; - guint8 ip_temp[4]; + /* + * If we have a connection with this same cookie then they are + * probably just telling us they weren't able to connect to us + * and we should try connecting to them, instead. Or they want + * to go through a proxy. + */ + conn = peer_connection_find_by_cookie(od, sn, args->cookie); + if ((conn != NULL) && (conn->type == args->type)) + { + gaim_debug_info("oscar", "Remote user wants to try a " + "different connection method\n"); + g_free(conn->proxyip); + g_free(conn->clientip); + g_free(conn->verifiedip); + if (args->use_proxy) + conn->proxyip = g_strdup(args->proxyip); + else + conn->proxyip = NULL; + conn->verifiedip = g_strdup(args->verifiedip); + conn->clientip = g_strdup(args->clientip); + conn->port = args->port; + conn->use_proxy |= args->use_proxy; + conn->lastrequestnumber++; + peer_connection_trynext(conn); + return; + } - guint16 len; - PeerProxyInfo *proxy_info; + /* If this is a direct IM, then close any existing session */ + if (args->type == OSCAR_CAPABILITY_DIRECTIM) + { + conn = peer_connection_find_by_type(od, sn, args->type); + if (conn != NULL) + { + /* Close the old direct IM and start a new one */ + gaim_debug_info("oscar", "Received new direct IM request " + "from %s. Destroying old connection.\n", sn); + peer_connection_destroy(conn, PEER_DISCONNECT_REMOTE_CLOSED); + } + } - if(!(proxy_info = malloc(sizeof(PeerProxyInfo)))) - return NULL; + /* Check for proper arguments */ + if (args->type == OSCAR_CAPABILITY_SENDFILE) + { + if ((args->info.sendfile.filename == NULL) || + (args->info.sendfile.totsize == 0) || + (args->info.sendfile.totfiles == 0)) + { + gaim_debug_warning("oscar", + "%s tried to send you a file with incomplete " + "information.\n", sn); + return; + } + } - aim_bstream_init(&bs_hdr, hdr_buf, AIM_RV_PROXY_HDR_LEN); - if (aim_bstream_recv(&bs_hdr, conn->fd, AIM_RV_PROXY_HDR_LEN) == AIM_RV_PROXY_HDR_LEN) { - aim_bstream_rewind(&bs_hdr); - len = aimbs_get16(&bs_hdr); - proxy_info->packet_ver = aimbs_get16(&bs_hdr); - proxy_info->cmd_type = aimbs_get16(&bs_hdr); - proxy_info->unknownA = aimbs_get32(&bs_hdr); - proxy_info->flags = aimbs_get16(&bs_hdr); - if(proxy_info->cmd_type == AIM_RV_PROXY_READY) { - /* Do a little victory dance - * A ready packet contains no additional information */ - } else if(proxy_info->cmd_type == AIM_RV_PROXY_ERROR) { - if(len == AIM_RV_PROXY_ERROR_LEN - 2) { - body_len = AIM_RV_PROXY_ERROR_LEN - AIM_RV_PROXY_HDR_LEN; - body_buf = malloc(body_len); - aim_bstream_init(&bs_body, body_buf, body_len); - if (aim_bstream_recv(&bs_body, conn->fd, body_len) == body_len) { - aim_bstream_rewind(&bs_body); - proxy_info->err_code = aimbs_get16(&bs_body); - } else { - gaim_debug_warning("oscar","error reading rv proxy error packet\n"); - aim_conn_close(sess, conn); - free(proxy_info); - proxy_info = NULL; - } - } else { - gaim_debug_warning("oscar","invalid length for proxy error packet\n"); - free(proxy_info); - proxy_info = NULL; - } - } else if(proxy_info->cmd_type == AIM_RV_PROXY_ACK) { - if(len == AIM_RV_PROXY_ACK_LEN - 2) { - body_len = AIM_RV_PROXY_ACK_LEN - AIM_RV_PROXY_HDR_LEN; - body_buf = malloc(body_len); - aim_bstream_init(&bs_body, body_buf, body_len); - if (aim_bstream_recv(&bs_body, conn->fd, body_len) == body_len) { - int i; - aim_bstream_rewind(&bs_body); - proxy_info->port = aimbs_get16(&bs_body); - for(i=0; i<4; i++) - ip_temp[i] = aimbs_get8(&bs_body); - snprintf(str_ip, sizeof(str_ip), "%hhu.%hhu.%hhu.%hhu", - ip_temp[0], ip_temp[1], - ip_temp[2], ip_temp[3]); - proxy_info->ip = strdup(str_ip); - } else { - gaim_debug_warning("oscar","error reading rv proxy error packet\n"); - aim_conn_close(sess, conn); - free(proxy_info); - proxy_info = NULL; - } - } else { - gaim_debug_warning("oscar","invalid length for proxy error packet\n"); - free(proxy_info); - proxy_info = NULL; - } - } else { - gaim_debug_warning("oscar","unknown type for aim rendezvous proxy packet\n"); + conn = peer_connection_new(od, args->type, sn); + memcpy(conn->cookie, args->cookie, 8); + if (args->use_proxy) + conn->proxyip = g_strdup(args->proxyip); + conn->clientip = g_strdup(args->clientip); + conn->verifiedip = g_strdup(args->verifiedip); + conn->port = args->port; + conn->use_proxy |= args->use_proxy; + conn->lastrequestnumber++; + + if (args->type == OSCAR_CAPABILITY_DIRECTIM) + { + buf = g_strdup_printf(_("%s has just asked to directly connect to %s"), + sn, gaim_account_get_username(account)); + + gaim_request_action(conn, NULL, buf, + _("This requires a direct connection between " + "the two computers and is necessary for IM " + "Images. Because your IP address will be " + "revealed, this may be considered a privacy " + "risk."), + GAIM_DEFAULT_ACTION_NONE, conn, 2, + _("_Connect"), G_CALLBACK(peer_connection_got_proposition_yes_cb), + _("Cancel"), G_CALLBACK(peer_connection_got_proposition_no_cb)); + } + else if (args->type == OSCAR_CAPABILITY_SENDFILE) + { + gchar *filename; + + conn->xfer = gaim_xfer_new(account, GAIM_XFER_RECEIVE, sn); + conn->xfer->data = conn; + gaim_xfer_ref(conn->xfer); + gaim_xfer_set_size(conn->xfer, args->info.sendfile.totsize); + + /* Set the file name */ + if (g_utf8_validate(args->info.sendfile.filename, -1, NULL)) + filename = g_strdup(args->info.sendfile.filename); + else + filename = gaim_utf8_salvage(args->info.sendfile.filename); + + if (args->info.sendfile.subtype == AIM_OFT_SUBTYPE_SEND_DIR) + { + /* + * If they are sending us a directory then the last character + * of the file name will be an asterisk. We don't want to + * save stuff to a directory named "*" so we remove the + * asterisk from the file name. + */ + char *tmp = strrchr(filename, '\\'); + if ((tmp != NULL) && (tmp[1] == '*')) + tmp[0] = '\0'; } - } else { - gaim_debug_warning("oscar","error reading header of rv proxy packet\n"); - aim_conn_close(sess, conn); - free(proxy_info); - proxy_info = NULL; + gaim_xfer_set_filename(conn->xfer, filename); + g_free(filename); + + /* + * Set the message (unless this is the dummy message from an + * ICQ client or an empty message from an AIM client. + * TODO: Maybe we should strip HTML and then see if strlen>0? + */ + if ((message != NULL) && + (g_ascii_strncasecmp(message, "<ICQ_COOL_FT>", 13) != 0) && + (g_ascii_strcasecmp(message, "<HTML>") != 0)) + { + gaim_xfer_set_message(conn->xfer, message); + } + + /* Setup our I/O op functions */ + gaim_xfer_set_init_fnc(conn->xfer, peer_oft_recvcb_init); + gaim_xfer_set_end_fnc(conn->xfer, peer_oft_recvcb_end); + gaim_xfer_set_request_denied_fnc(conn->xfer, peer_oft_cb_generic_cancel); + gaim_xfer_set_cancel_recv_fnc(conn->xfer, peer_oft_cb_generic_cancel); + gaim_xfer_set_ack_fnc(conn->xfer, peer_oft_recvcb_ack_recv); + + /* Now perform the request */ + gaim_xfer_request(conn->xfer); } - if(body_buf) { - free(body_buf); - body_buf = NULL; - } - return proxy_info; } + +/*******************************************************************/ +/* End code for establishing a peer connection */ +/*******************************************************************/
--- a/src/protocols/oscar/peer.h Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/peer.h Fri Apr 07 05:10:56 2006 +0000 @@ -19,55 +19,92 @@ */ /* - * OFT Services - * - * For all of the above #defines, the number is the subtype - * of the SNAC. For OFT #defines, the number is the - * "hdrtype" which comes after the magic string and OFT - * packet length. - * - * I'm pretty sure the ODC ones are arbitrary right now, - * that should be changed. + * OFT and ODC Services */ #ifndef _PEER_H_ #define _PEER_H_ -typedef struct _PeerConnection PeerConnection; -typedef struct _PeerFrame PeerFrame; -typedef struct _PeerProxyInfo PeerProxyInfo; +#include "ft.h" -#define AIM_CB_FAM_OFT 0xfffe /* OFT/Rvous */ +typedef struct _OdcFrame OdcFrame; +typedef struct _OftFrame OftFrame; +typedef struct _ProxyFrame ProxyFrame; +typedef struct _NewPeerConnectionData NewPeerConnectionData; +typedef struct _PeerConnection PeerConnection; -#define PEER_TYPE_DIRECTIMCONNECTREQ 0x0001 /* connect request -- actually an OSCAR CAP */ -#define PEER_TYPE_DIRECTIMINCOMING 0x0002 -#define PEER_TYPE_DIRECTIMDISCONNECT 0x0003 -#define PEER_TYPE_DIRECTIMTYPING 0x0004 -#define PEER_TYPE_DIRECTIM_ESTABLISHED 0x0005 +typedef enum +{ + PEER_DISCONNECT_DONE, + PEER_DISCONNECT_LOCAL_CLOSED, + PEER_DISCONNECT_REMOTE_CLOSED, + PEER_DISCONNECT_REMOTE_REFUSED, + PEER_DISCONNECT_LOST_CONNECTION, + PEER_DISCONNECT_INVALID_DATA, + PEER_DISCONNECT_COULD_NOT_CONNECT, + PEER_DISCONNECT_RETRYING +} PeerDisconnectReason; -#define PEER_TYPE_PROMPT 0x0101 /* "I am going to send you this file, is that ok?" */ -#define PEER_TYPE_RESUMESOMETHING 0x0106 /* I really don't know */ -#define PEER_TYPE_ACK 0x0202 /* "Yes, it is ok for you to send me that file" */ -#define PEER_TYPE_DONE 0x0204 /* "I received that file with no problems, thanks a bunch" */ -#define PEER_TYPE_RESUME 0x0205 /* Resume transferring, sent by whoever paused? */ -#define PEER_TYPE_RESUMEACK 0x0207 /* Not really sure */ +#define PEER_CONNECTION_FLAG_INITIATED_BY_ME 0x0001 +#define PEER_CONNECTION_FLAG_APPROVED 0x0002 +#define PEER_CONNECTION_FLAG_TRIED_VERIFIEDIP 0x0004 +#define PEER_CONNECTION_FLAG_TRIED_CLIENTIP 0x0008 +#define PEER_CONNECTION_FLAG_TRIED_INCOMING 0x0010 +#define PEER_CONNECTION_FLAG_TRIED_PROXY 0x0020 +#define PEER_CONNECTION_FLAG_IS_INCOMING 0x0040 + +#define PEER_TYPE_PROMPT 0x0101 /* "I am going to send you this file, is that ok?" */ +#define PEER_TYPE_RESUMESOMETHING 0x0106 /* I really don't know */ +#define PEER_TYPE_ACK 0x0202 /* "Yes, it is ok for you to send me that file" */ +#define PEER_TYPE_DONE 0x0204 /* "I received that file with no problems, thanks a bunch" */ +#define PEER_TYPE_RESUME 0x0205 /* Resume transferring, sent by whoever paused? */ +#define PEER_TYPE_RESUMEACK 0x0207 /* Not really sure */ #define PEER_TYPE_GETFILE_REQUESTLISTING 0x1108 /* "I have a listing.txt file, do you want it?" */ #define PEER_TYPE_GETFILE_RECEIVELISTING 0x1209 /* "Yes, please send me your listing.txt file" */ #define PEER_TYPE_GETFILE_RECEIVEDLISTING 0x120a /* received corrupt listing.txt file? I'm just guessing about this one... */ -#define PEER_TYPE_GETFILE_ACKLISTING 0x120b /* "I received the listing.txt file successfully" */ -#define PEER_TYPE_GETFILE_REQUESTFILE 0x120c /* "Please send me this file" */ +#define PEER_TYPE_GETFILE_ACKLISTING 0x120b /* "I received the listing.txt file successfully" */ +#define PEER_TYPE_GETFILE_REQUESTFILE 0x120c /* "Please send me this file" */ -#define PEER_TYPE_ESTABLISHED 0xFFFF /* connection to buddy initiated */ +/* + * For peer proxying + */ +#define PEER_PROXY_SERVER "ars.oscar.aol.com" +#define PEER_PROXY_PORT 5190 /* The port we should always connect to */ +#define PEER_PROXY_PACKET_VERSION 0x044a -struct _PeerFrame +/* Thanks to Keith Lea and the Joust project for documenting these */ +#define PEER_PROXY_TYPE_ERROR 0x0001 +#define PEER_PROXY_TYPE_CREATE 0x0002 +#define PEER_PROXY_TYPE_CREATED 0x0003 +#define PEER_PROXY_TYPE_JOIN 0x0004 +#define PEER_PROXY_TYPE_READY 0x0005 + +struct _OdcFrame { -#if 0 - char magic[4]; /* 0 */ - guint16 length; /* 4 */ + /* guchar magic[4]; */ /* 0 */ + /* guint16 length; */ /* 4 */ + guint16 type; /* 6 */ + guint16 subtype; /* 8 */ + /* Unknown */ /* 10 */ + guchar cookie[8]; /* 12 */ + /* Unknown */ + /* guint32 payloadlength; */ /* 28 */ + guint16 encoding; /* 32 */ + /* Unknown */ + guint16 flags; /* 38 */ + /* Unknown */ + guchar sn[32]; /* 44 */ + /* Unknown */ + ByteStream payload; /* 76 */ +}; + +struct _OftFrame +{ + /* guchar magic[4]; */ /* 0 */ + /* guint16 length; */ /* 4 */ guint16 type; /* 6 */ -#endif - guchar bcookie[8]; /* 8 */ + guchar cookie[8]; /* 8 */ guint16 encrypt; /* 16 */ guint16 compress; /* 18 */ guint16 totfiles; /* 20 */ @@ -84,88 +121,162 @@ guint32 rfcsum; /* 56 */ guint32 nrecvd; /* 60 */ guint32 recvcsum; /* 64 */ - char idstring[32]; /* 68 */ + guchar idstring[32]; /* 68 */ guint8 flags; /* 100 */ guint8 lnameoffset; /* 101 */ guint8 lsizeoffset; /* 102 */ - char dummy[69]; /* 103 */ - char macfileinfo[16]; /* 172 */ + guchar dummy[69]; /* 103 */ + guchar macfileinfo[16]; /* 172 */ guint16 nencode; /* 188 */ guint16 nlanguage; /* 190 */ - char name[64]; /* 192 */ + guchar *name; /* 192 */ + size_t name_length; /* Payload? */ /* 256 */ }; -struct _PeerProxyInfo { - guint16 packet_ver; - guint16 cmd_type; - guint16 flags; - char* ip; /* IP address sent along with this packet */ - guint16 port; /* This is NOT the port we should use to connect. Always connect to 5190 */ - guchar cookie[8]; - guint32 unknownA; - guint16 err_code; /* Valid only for cmd_type of AIM_RV_PROXY_ERROR */ - OscarConnection *conn; - OscarSession *sess; +struct _ProxyFrame +{ + /* guint16 length; */ /* 0 */ + guint16 version; /* 2 */ + guint16 type; /* 4 */ + guint32 unknown; /* 6 */ + guint16 flags; /* 10 */ + ByteStream payload; /* 12 */ }; -struct _PeerConnection { - guchar cookie[8]; - char *sn; - char *proxyip; - char *clientip; - char *verifiedip; - guint16 port; - - int send_or_recv; /* Send or receive */ - int method; /* What method is being used to transfer this file? DIRECT, REDIR, or PROXY */ - int stage; /* At what stage was a proxy requested? NONE, STG1, STG2*/ - int xfer_reffed; /* There are many timers, but we should only ref the xfer once */ - int redir_attempted; /* Have we previously attempted to redirect the connection? */ - guint32 res_bytes; /* The bytes already received for resuming a transfer */ - - OscarConnection *conn; - OscarSession *sess; - int success; /* Was the connection successful? Used for timing out the transfer. */ - PeerFrame fh; - PeerProxyInfo *proxy_info; +struct _NewPeerConnectionData +{ + GaimConnection *gc; + PeerConnection *conn; }; -int aim_handlerendconnect(OscarSession *sess, OscarConnection *cur); -int aim_rxdispatch_rendezvous(OscarSession *sess, FlapFrame *fr); +struct _PeerConnection +{ + OscarData *od; + OscarCapability type; + char *sn; + guchar magic[4]; + guchar cookie[8]; + guint16 lastrequestnumber; + + gboolean ready; + int flags; /**< Bitmask of PEER_CONNECTION_FLAG_ */ + time_t lastactivity; /**< Time of last transmit. */ + guint destroy_timeout; + PeerDisconnectReason disconnect_reason; + + /** + * A pointer to either an OdcFrame or an OftFrame. + */ + gpointer frame; + + /** + * This is only used while the remote user is attempting to + * connect to us. + */ + int listenerfd; + int fd; -/* - * OFT - */ -int aim_sendfile_listen(OscarSession *sess, PeerConnection *peer_connection, int listenfd); -int aim_oft_sendheader(OscarSession *sess, guint16 type, PeerConnection *peer_connection); -guint32 aim_oft_checksum_chunk(const guint8 *buffer, int bufferlen, guint32 prevcheck); -guint32 aim_oft_checksum_file(char *filename); -int aim_oft_sendheader(OscarSession *sess, guint16 type, PeerConnection *peer_connection); -PeerConnection *aim_oft_createinfo(OscarSession *sess, const guchar *cookie, const char *sn, - const char *ip, guint16 port, guint32 size, guint32 modtime, char *filename, int send_or_recv, - int method, int stage); -int aim_oft_destroyinfo(PeerConnection *peer_connection); + guint watcher_incoming; + guint watcher_outgoing; + + ByteStream buffer_incoming; + GaimCircBuffer *buffer_outgoing; + + /** + * IP address of the proxy server, if applicable. + */ + gchar *proxyip; + + /** + * IP address of the remote user from THEIR point of view. + */ + gchar *clientip; + + /** + * IP address of the remote user from the oscar server's + * point of view. + */ + gchar *verifiedip; + + guint16 port; + gboolean use_proxy; + + /* TODOFT */ + GaimXfer *xfer; + OftFrame xferdata; + guint sending_data_timer; +}; /* - * ODC + * For all peer connections + */ + +/** + * Create a new PeerConnection structure and initialize it with some + * sane defaults. + * + * @param type The type of the peer connection. One of + * OSCAR_CAPABILITY_DIRECTIM or OSCAR_CAPABILITY_SENDFILE. */ -int aim_odc_send_typing(OscarSession *sess, OscarConnection *conn, int typing); -int aim_odc_send_im(OscarSession *sess, OscarConnection *conn, const char *msg, int len, int encoding, int isawaymsg); -const char *aim_odc_getsn(OscarConnection *conn); -const guchar *aim_odc_getcookie(OscarConnection *conn); -OscarConnection *aim_odc_getconn(OscarSession *sess, const char *sn); -OscarConnection *aim_odc_initiate(OscarSession *sess, const char *sn, int listenfd, - const guint8 *localip, guint16 port, const guchar *mycookie); -OscarConnection *aim_odc_connect(OscarSession *sess, const char *sn, const char *addr, const guchar *cookie); +PeerConnection *peer_connection_new(OscarData *od, OscarCapability type, const char *sn); + +void peer_connection_destroy(PeerConnection *conn, PeerDisconnectReason reason); +void peer_connection_schedule_destroy(PeerConnection *conn, PeerDisconnectReason reason); +PeerConnection *peer_connection_find_by_type(OscarData *od, const char *sn, OscarCapability type); +PeerConnection *peer_connection_find_by_cookie(OscarData *od, const char *sn, const guchar *cookie); + +void peer_connection_listen_cb(gpointer data, gint source, GaimInputCondition cond); +void peer_connection_recv_cb(gpointer data, gint source, GaimInputCondition cond); +void peer_connection_send(PeerConnection *conn, ByteStream *bs); + +void peer_connection_trynext(PeerConnection *conn); +void peer_connection_finalize_connection(PeerConnection *conn); +void peer_connection_propose(OscarData *od, OscarCapability type, const char *sn); +void peer_connection_got_proposition(OscarData *od, const gchar *sn, const gchar *message, IcbmArgsCh2 *args); + +/* + * For ODC + */ +void peer_odc_close(PeerConnection *conn); +void peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs); +void peer_odc_send_cookie(PeerConnection *conn); +void peer_odc_send_typing(PeerConnection *conn, GaimTypingState typing); +void peer_odc_send_im(PeerConnection *conn, const char *msg, int len, int encoding, gboolean autoreply); /* - * Rendezvous proxy + * For OFT */ -PeerProxyInfo *aim_rv_proxy_createinfo(OscarSession *sess, const guchar *cookie, guint16 port); -int aim_rv_proxy_init_recv(PeerProxyInfo *proxy_info); -int aim_rv_proxy_init_send(PeerProxyInfo *proxy_info); +void peer_oft_close(PeerConnection *conn); +void peer_oft_recv_frame(PeerConnection *conn, ByteStream *bs); +void peer_oft_send_prompt(PeerConnection *conn); + +/* Xfer callbacks for receiving a file */ +void peer_oft_recvcb_init(GaimXfer *xfer); +void peer_oft_recvcb_end(GaimXfer *xfer); +void peer_oft_recvcb_ack_recv(GaimXfer *xfer, const guchar *buffer, size_t size); + +/* Xfer callbacks for sending a file */ +void peer_oft_sendcb_init(GaimXfer *xfer); +void peer_oft_sendcb_ack(GaimXfer *xfer, const guchar *buffer, size_t size); + +/* Xfer callbacks for both sending and receiving */ +void peer_oft_cb_generic_cancel(GaimXfer *xfer); -PeerProxyInfo *aim_rv_proxy_read(OscarSession *sess, OscarConnection *conn); +/* + * For peer proxying + */ +void peer_proxy_connection_established_cb(gpointer data, gint source, GaimInputCondition cond); + +#if 0 +int peer_oft_sendheader(OscarData *od, guint16 type, PeerConnection *peer_connection); +guint32 peer_oft_checksum_chunk(const guint8 *buffer, int bufferlen, guint32 prevcheck); +guint32 peer_oft_checksum_file(char *filename); +int peer_oft_sendheader(OscarData *od, guint16 type, PeerConnection *peer_connection); +PeerConnection *peer_oft_createinfo(OscarData *od, const guchar *cookie, const char *sn, + const char *ip, guint16 port, guint32 size, guint32 modtime, char *filename, int send_or_recv, + int method, int stage); +int peer_oft_destroyinfo(PeerConnection *peer_connection); +#endif #endif /* _PEER_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/oscar/peer_proxy.c Fri Apr 07 05:10:56 2006 +0000 @@ -0,0 +1,362 @@ +/* + * 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 +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "oscar.h" +#include "peer.h" + +static void +peer_proxy_send(PeerConnection *conn, ProxyFrame *frame) +{ + size_t length; + ByteStream bs; + + gaim_debug_info("oscar", "Outgoing peer proxy frame with " + "type=0x%04hx, unknown=0x%08x, " + "flags=0x%04hx, and payload length=%hd\n", + frame->type, frame->unknown, + frame->flags, frame->payload.len); + + length = 12 + frame->payload.len; + byte_stream_init(&bs, malloc(length), length); + byte_stream_put16(&bs, length - 2); + byte_stream_put16(&bs, PEER_PROXY_PACKET_VERSION); + byte_stream_put16(&bs, frame->type); + byte_stream_put32(&bs, frame->unknown); + byte_stream_put16(&bs, frame->flags); + byte_stream_putraw(&bs, frame->payload.data, frame->payload.len); + + peer_connection_send(conn, &bs); + + free(bs.data); +} + +/** + * Create a rendezvous "init send" packet and send it on its merry way. + * This is the first packet sent to the proxy server by the first client + * to indicate that this will be a proxied connection + * + * @param conn The peer connection. + */ +static void +peer_proxy_send_create_new_conn(PeerConnection *conn) +{ + ProxyFrame frame; + GaimAccount *account; + const gchar *sn; + guint8 sn_length; + size_t length; + + memset(&frame, 0, sizeof(ProxyFrame)); + frame.type = PEER_PROXY_TYPE_CREATE; + frame.flags = 0x0000; + + account = gaim_connection_get_account(conn->od->gc); + sn = gaim_account_get_username(account); + sn_length = strlen(sn); + length = 1 + sn_length + 8 + 20; + byte_stream_init(&frame.payload, malloc(length), length); + byte_stream_put8(&frame.payload, sn_length); + byte_stream_putraw(&frame.payload, (const guint8 *)sn, sn_length); + byte_stream_putraw(&frame.payload, conn->cookie, 8); + + byte_stream_put16(&frame.payload, 0x0001); /* Type */ + byte_stream_put16(&frame.payload, 16); /* Length */ + byte_stream_putcaps(&frame.payload, conn->type); /* Value */ + + peer_proxy_send(conn, &frame); +} + +/** + * Create a rendezvous "init recv" packet and send it on its merry way. + * This is the first packet sent to the proxy server by the second client + * involved in this rendezvous proxy session. + * + * @param conn The peer connection. + * @param pin The 2 byte PIN sent to us by the other user. This acts + * as our passcode when establishing the proxy session. + */ +static void +peer_proxy_send_join_existing_conn(PeerConnection *conn, guint16 pin) +{ + ProxyFrame frame; + GaimAccount *account; + const gchar *sn; + guint8 sn_length; + size_t length; + + memset(&frame, 0, sizeof(ProxyFrame)); + frame.type = PEER_PROXY_TYPE_JOIN; + frame.flags = 0x0000; + + account = gaim_connection_get_account(conn->od->gc); + sn = gaim_account_get_username(account); + sn_length = strlen(sn); + length = 1 + sn_length + 2 + 8 + 20; + byte_stream_init(&frame.payload, malloc(length), length); + byte_stream_put8(&frame.payload, sn_length); + byte_stream_putraw(&frame.payload, (const guint8 *)sn, sn_length); + byte_stream_put16(&frame.payload, pin); + byte_stream_putraw(&frame.payload, conn->cookie, 8); + + byte_stream_put16(&frame.payload, 0x0001); /* Type */ + byte_stream_put16(&frame.payload, 16); /* Length */ + byte_stream_putcaps(&frame.payload, conn->type); /* Value */ + + peer_proxy_send(conn, &frame); +} + +/** + * Handle an incoming peer proxy negotiation frame. + */ +static void +peer_proxy_recv_frame(PeerConnection *conn, ProxyFrame *frame) +{ + gaim_debug_info("oscar", "Incoming peer proxy frame with " + "type=0x%04hx, unknown=0x%08x, " + "flags=0x%04hx, and payload length=%hd\n", frame->type, + frame->unknown, frame->flags, frame->payload.len); + + if (frame->type == PEER_PROXY_TYPE_CREATED) + { + /* + * Read in 2 byte port then 4 byte IP and tell the + * remote user to connect to it by sending an ICBM. + */ + guint16 pin; + int i; + guint8 ip[4]; + + pin = byte_stream_get16(&frame->payload); + for (i = 0; i < 4; i++) + ip[i] = byte_stream_get8(&frame->payload); + if (conn->type == OSCAR_CAPABILITY_DIRECTIM) + aim_im_sendch2_odc_requestproxy(conn->od, + conn->cookie, + conn->sn, ip, pin, ++conn->lastrequestnumber); + else if (conn->type == OSCAR_CAPABILITY_SENDFILE) + { + aim_im_sendch2_sendfile_requestproxy(conn->od, + conn->cookie, conn->sn, + ip, pin, ++conn->lastrequestnumber, + (const gchar *)conn->xferdata.name, + conn->xferdata.size, conn->xferdata.totfiles); + } + } + else if (frame->type == PEER_PROXY_TYPE_READY) + { + gaim_input_remove(conn->watcher_incoming); + conn->watcher_incoming = 0; + + peer_connection_finalize_connection(conn); + } + else if (frame->type == PEER_PROXY_TYPE_ERROR) + { + if (byte_stream_empty(&frame->payload) >= 2) + { + guint16 error; + const char *msg; + error = byte_stream_get16(&frame->payload); + if (error == 0x000d) + msg = "bad request"; + else if (error == 0x0010) + msg = "initial request timed out"; + else if (error == 0x001a) + msg ="accept period timed out"; + else + msg = "unknown reason"; + gaim_debug_info("oscar", "Proxy negotiation failed with " + "error 0x%04hx: %s\n", error, msg); + } + else + { + gaim_debug_warning("oscar", "Proxy negotiation failed with " + "an unknown error\n"); + } + peer_connection_trynext(conn); + } + else + { + gaim_debug_warning("oscar", "Unknown peer proxy frame type 0x%04hx.\n", + frame->type); + } +} + +static void +peer_proxy_connection_recv_cb(gpointer data, gint source, GaimInputCondition cond) +{ + PeerConnection *conn; + ssize_t read; + guint8 header[12]; + ProxyFrame *frame; + + conn = data; + frame = conn->frame; + + /* Start reading a new proxy frame */ + if (frame == NULL) + { + /* Peek at the first 12 bytes to get the length */ + read = recv(conn->fd, &header, 12, MSG_PEEK); + + /* Check if the proxy server closed the connection */ + if (read == 0) + { + gaim_debug_info("oscar", "Peer proxy server closed connection\n"); + peer_connection_trynext(conn); + return; + } + + /* If there was an error then close the connection */ + if (read == -1) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No worries */ + return; + + gaim_debug_info("oscar", "Lost connection with peer proxy server\n"); + peer_connection_trynext(conn); + return; + } + + conn->lastactivity = time(NULL); + + /* If we don't even have the first 12 bytes then do nothing */ + if (read < 12) + return; + + /* Read the first 12 bytes (frame length and header) */ + read = recv(conn->fd, &header, 12, 0); + + /* We only support a specific version of the proxy protocol */ + if (aimutil_get16(&header[2]) != PEER_PROXY_PACKET_VERSION) + { + gaim_debug_warning("oscar", "Expected peer proxy protocol " + "version %u but received version %u. Closing " + "connection.\n", PEER_PROXY_PACKET_VERSION, + aimutil_get16(&header[2])); + peer_connection_trynext(conn); + return; + } + + /* Initialize a new temporary ProxyFrame for incoming data */ + frame = g_new0(ProxyFrame, 1); + frame->payload.len = aimutil_get16(&header[0]) - 10; + frame->version = aimutil_get16(&header[2]); + frame->type = aimutil_get16(&header[4]); + frame->unknown = aimutil_get16(&header[6]); + frame->flags = aimutil_get16(&header[10]); + if (frame->payload.len > 0) + frame->payload.data = g_new(guint8, frame->payload.len); + conn->frame = frame; + } + + /* If this frame has a payload then attempt to read it */ + if (frame->payload.len - frame->payload.offset > 0) + { + /* Read data into the temporary buffer until it is complete */ + read = recv(conn->fd, + &frame->payload.data[frame->payload.offset], + frame->payload.len - frame->payload.offset, + 0); + + /* Check if the proxy server closed the connection */ + if (read == 0) + { + gaim_debug_info("oscar", "Peer proxy server closed connection\n"); + g_free(frame->payload.data); + g_free(frame); + conn->frame = NULL; + peer_connection_trynext(conn); + return; + } + + if (read == -1) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + /* No worries */ + return; + + gaim_debug_info("oscar", "Lost connection with peer proxy server\n"); + g_free(frame->payload.data); + g_free(frame); + conn->frame = NULL; + peer_connection_trynext(conn); + return; + } + } + + conn->lastactivity = time(NULL); + frame->payload.offset += read; + if (frame->payload.offset < frame->payload.len) + /* Waiting for more data to arrive */ + return; + + /* We have a complete proxy frame! Handle it and continue reading */ + conn->frame = NULL; + byte_stream_rewind(&frame->payload); + peer_proxy_recv_frame(conn, frame); + g_free(frame->payload.data); + g_free(frame); +} + +/** + * We tried to make an outgoing connection to a proxy server. It + * either connected or failed to connect. + */ +void +peer_proxy_connection_established_cb(gpointer data, gint source, GaimInputCondition cond) +{ + NewPeerConnectionData *new_conn_data; + GaimConnection *gc; + PeerConnection *conn; + + new_conn_data = data; + gc = new_conn_data->gc; + conn = new_conn_data->conn; + g_free(new_conn_data); + + if (!g_list_find(gaim_connections_get_all(), gc)) + { + if (source >= 0) + close(source); + return; + } + + if (source < 0) + { + peer_connection_trynext(conn); + return; + } + + conn->fd = source; + conn->watcher_incoming = gaim_input_add(conn->fd, + GAIM_INPUT_READ, peer_proxy_connection_recv_cb, conn); + + if (conn->proxyip != NULL) + /* Connect to the session created by the remote user */ + peer_proxy_send_join_existing_conn(conn, conn->port); + else + /* Create a new session */ + peer_proxy_send_create_new_conn(conn); +}
--- a/src/protocols/oscar/rxhandlers.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/rxhandlers.c Fri Apr 07 05:10:56 2006 +0000 @@ -18,31 +18,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - * rxhandlers.c - * - * This file contains most all of the incoming packet handlers, along - * with aim_rxdispatch(), the Rx dispatcher. Queue/list management is - * actually done in aim_rxqueue.c. - * - */ - #include "oscar.h" #include "peer.h" -struct aim_rxcblist_s { - guint16 family; - guint16 type; - aim_rxcallback_t handler; - guint16 flags; - struct aim_rxcblist_s *next; -}; - -faim_internal aim_module_t *aim__findmodulebygroup(OscarSession *sess, guint16 group) +aim_module_t *aim__findmodulebygroup(OscarData *od, guint16 group) { aim_module_t *cur; - for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { + for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) { if (cur->family == group) return cur; } @@ -50,11 +33,11 @@ return NULL; } -faim_internal aim_module_t *aim__findmodule(OscarSession *sess, const char *name) +aim_module_t *aim__findmodule(OscarData *od, const char *name) { aim_module_t *cur; - for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { + for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) { if (strcmp(name, cur->name) == 0) return cur; } @@ -62,171 +45,63 @@ return NULL; } -faim_internal int aim__registermodule(OscarSession *sess, int (*modfirst)(OscarSession *, aim_module_t *)) +int aim__registermodule(OscarData *od, int (*modfirst)(OscarData *, aim_module_t *)) { aim_module_t *mod; - if (!sess || !modfirst) + if (!od || !modfirst) return -1; - if (!(mod = malloc(sizeof(aim_module_t)))) - return -1; - memset(mod, 0, sizeof(aim_module_t)); + mod = g_new0(aim_module_t, 1); - if (modfirst(sess, mod) == -1) { + if (modfirst(od, mod) == -1) { free(mod); return -1; } - if (aim__findmodule(sess, mod->name)) { + if (aim__findmodule(od, mod->name)) { if (mod->shutdown) - mod->shutdown(sess, mod); + mod->shutdown(od, mod); free(mod); return -1; } - mod->next = (aim_module_t *)sess->modlistv; - sess->modlistv = mod; + mod->next = (aim_module_t *)od->modlistv; + od->modlistv = mod; gaim_debug_misc("oscar", "registered module %s (family 0x%04x, version = 0x%04x, tool 0x%04x, tool version 0x%04x)\n", mod->name, mod->family, mod->version, mod->toolid, mod->toolversion); return 0; } -faim_internal void aim__shutdownmodules(OscarSession *sess) +void aim__shutdownmodules(OscarData *od) { aim_module_t *cur; - for (cur = (aim_module_t *)sess->modlistv; cur; ) { + for (cur = (aim_module_t *)od->modlistv; cur; ) { aim_module_t *tmp; tmp = cur->next; if (cur->shutdown) - cur->shutdown(sess, cur); + cur->shutdown(od, cur); free(cur); cur = tmp; } - sess->modlistv = NULL; + od->modlistv = NULL; return; } -static int consumesnac(OscarSession *sess, FlapFrame *rx) -{ - aim_module_t *cur; - aim_modsnac_t snac; - - if (aim_bstream_empty(&rx->data) < 10) - return 0; - - snac.family = aimbs_get16(&rx->data); - snac.subtype = aimbs_get16(&rx->data); - snac.flags = aimbs_get16(&rx->data); - snac.id = aimbs_get32(&rx->data); - - /* SNAC flags are apparently uniform across all SNACs, so we handle them here */ - if (snac.flags & 0x0001) { - /* - * This means the SNAC will be followed by another SNAC with - * related information. We don't need to do anything about - * this here. - */ - } - if (snac.flags & 0x8000) { - /* - * This packet contains the version of the family that this SNAC is - * in. You get this when your SSI module is version 2 or higher. - * For now we have no need for this, but you could always save - * it as a part of aim_modnsac_t, or something. The format is... - * 2 byte length of total mini-header (which is 6 bytes), then TLV - * of type 0x0001, length 0x0002, value is the 2 byte version - * number - */ - aim_bstream_advance(&rx->data, aimbs_get16(&rx->data)); - } - - for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { - - if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && - (cur->family != snac.family)) - continue; - - if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) - return 1; - - } - - return 0; -} - -static int consumenonsnac(OscarSession *sess, FlapFrame *rx, guint16 family, guint16 subtype) -{ - aim_module_t *cur; - aim_modsnac_t snac; - - snac.family = family; - snac.subtype = subtype; - snac.flags = snac.id = 0; - - for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { - - if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && - (cur->family != snac.family)) - continue; - - if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) - return 1; - - } - - return 0; -} - -static int negchan_middle(OscarSession *sess, FlapFrame *fr) -{ - aim_tlvlist_t *tlvlist; - char *msg = NULL; - guint16 code = 0; - aim_rxcallback_t userfunc; - int ret = 1; - - if (aim_bstream_empty(&fr->data) == 0) { - /* XXX should do something with this */ - return 1; - } - - /* Used only by the older login protocol */ - /* XXX remove this special case? */ - if (fr->conn->type == AIM_CONN_TYPE_AUTH) - return consumenonsnac(sess, fr, 0x0017, 0x0003); - - tlvlist = aim_tlvlist_read(&fr->data); - - if (aim_tlv_gettlv(tlvlist, 0x0009, 1)) - code = aim_tlv_get16(tlvlist, 0x0009, 1); - - if (aim_tlv_gettlv(tlvlist, 0x000b, 1)) - msg = aim_tlv_getstr(tlvlist, 0x000b, 1); - - if ((userfunc = aim_callhandler(sess, fr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR))) - ret = userfunc(sess, fr, code, msg); - - aim_tlvlist_free(&tlvlist); - - free(msg); - - return ret; -} - +#if 0 /* * Bleck functions get called when there's no non-bleck functions * around to cleanup the mess... */ -static int bleck(OscarSession *sess, FlapFrame *frame, ...) +static int bleck(OscarData *od, FlapFrame *frame, ...) { guint16 family, subtype; guint16 maxf, maxs; @@ -240,13 +115,13 @@ "FLAP NOP" }; static const int maxchannels = 5; - + /* XXX: this is ugly. and big just for debugging. */ static const char *literals[14][25] = { - {"Invalid", + {"Invalid", NULL }, - {"General", + {"General", "Invalid", "Error", "Client Ready", @@ -271,60 +146,60 @@ "Well Known URL", "NOP" }, - {"Location", + {"Location", "Invalid", "Error", "Request Rights", - "Rights Information", - "Set user information", - "Request User Information", - "User Information", + "Rights Information", + "Set user information", + "Request User Information", + "User Information", "Watcher Sub Request", "Watcher Notification" }, - {"Buddy List Management", - "Invalid", - "Error", + {"Buddy List Management", + "Invalid", + "Error", "Request Rights", "Rights Information", - "Add Buddy", - "Remove Buddy", - "Watcher List Query", - "Watcher List Response", - "Watcher SubRequest", - "Watcher Notification", - "Reject Notification", - "Oncoming Buddy", + "Add Buddy", + "Remove Buddy", + "Watcher List Query", + "Watcher List Response", + "Watcher SubRequest", + "Watcher Notification", + "Reject Notification", + "Oncoming Buddy", "Offgoing Buddy" }, - {"Messeging", + {"Messeging", "Invalid", - "Error", + "Error", "Add ICBM Parameter", - "Remove ICBM Parameter", + "Remove ICBM Parameter", "Request Parameter Information", "Parameter Information", - "Outgoing Message", + "Outgoing Message", "Incoming Message", "Evil Request", - "Evil Reply", + "Evil Reply", "Missed Calls", - "Message Error", + "Message Error", "Host Ack" }, - {"Advertisements", - "Invalid", - "Error", + {"Advertisements", + "Invalid", + "Error", "Request Ad", "Ad Data (GIFs)" }, - {"Invitation / Client-to-Client", + {"Invitation / Client-to-Client", "Invalid", "Error", "Invite a Friend", "Invitation Ack" }, - {"Administrative", + {"Administrative", "Invalid", "Error", "Information Request", @@ -336,12 +211,12 @@ "Account Delete Request", "Account Delete Reply" }, - {"Popups", + {"Popups", "Invalid", "Error", "Display Popup" }, - {"BOS", + {"BOS", "Invalid", "Error", "Request Rights", @@ -353,25 +228,25 @@ "Delete deny list entries", "Server Error" }, - {"User Lookup", + {"User Lookup", "Invalid", "Error", "Search Request", "Search Response" }, - {"Stats", + {"Stats", "Invalid", "Error", "Set minimum report interval", "Report Events" }, - {"Translate", + {"Translate", "Invalid", "Error", "Translate Request", "Translate Reply", }, - {"Chat Navigation", + {"Chat Navigation", "Invalid", "Error", "Request rights", @@ -379,10 +254,10 @@ "Request Room Information", "Request Occupant List", "Search for Room", - "Outgoing Message", + "Outgoing Message", "Incoming Message", - "Evil Request", - "Evil Reply", + "Evil Request", + "Evil Reply", "Chat Error", } }; @@ -390,207 +265,24 @@ maxf = sizeof(literals) / sizeof(literals[0]); maxs = sizeof(literals[0]) / sizeof(literals[0][0]); - if (frame->hdr.flap.channel == 0x02) { + if (frame->channel == 0x02) { + + family = byte_stream_get16(&frame->data); + subtype = byte_stream_get16(&frame->data); - family = aimbs_get16(&frame->data); - subtype = aimbs_get16(&frame->data); - if ((family < maxf) && (subtype+1 < maxs) && (literals[family][subtype] != NULL)) - gaim_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (%s)\n", channels[frame->hdr.flap.channel], family, subtype, literals[family][subtype+1]); + gaim_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (%s)\n", channels[frame->channel], family, subtype, literals[family][subtype+1]); else - gaim_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (no literal)\n", channels[frame->hdr.flap.channel], family, subtype); + gaim_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (no literal)\n", channels[frame->channel], family, subtype); } else { - if (frame->hdr.flap.channel <= maxchannels) - gaim_debug_misc("oscar", "bleck: channel %s (0x%02x)\n", channels[frame->hdr.flap.channel], frame->hdr.flap.channel); + if (frame->channel <= maxchannels) + gaim_debug_misc("oscar", "bleck: channel %s (0x%02x)\n", channels[frame->channel], frame->channel); else - gaim_debug_misc("oscar", "bleck: unknown channel 0x%02x\n", frame->hdr.flap.channel); + gaim_debug_misc("oscar", "bleck: unknown channel 0x%02x\n", frame->channel); } - - return 1; -} - -faim_export int aim_conn_addhandler(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 type, aim_rxcallback_t newhandler, guint16 flags) -{ - struct aim_rxcblist_s *newcb; - - if (!conn) - return -1; - - gaim_debug_misc("oscar", "aim_conn_addhandler: adding for %04x/%04x\n", family, type); - - if (!(newcb = (struct aim_rxcblist_s *)calloc(1, sizeof(struct aim_rxcblist_s)))) - return -1; - - newcb->family = family; - newcb->type = type; - newcb->flags = flags; - newcb->handler = newhandler ? newhandler : bleck; - newcb->next = NULL; - - if (!conn->handlerlist) - conn->handlerlist = (void *)newcb; - else { - struct aim_rxcblist_s *cur; - - for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur->next; cur = cur->next) - ; - cur->next = newcb; - } - - return 0; -} - -faim_export int aim_clearhandlers(OscarConnection *conn) -{ - struct aim_rxcblist_s *cur; - - if (!conn) - return -1; - - for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur; ) { - struct aim_rxcblist_s *tmp; - - tmp = cur->next; - free(cur); - cur = tmp; - } - conn->handlerlist = NULL; - - return 0; -} - -faim_internal aim_rxcallback_t aim_callhandler(OscarSession *sess, OscarConnection *conn, guint16 family, guint16 type) -{ - struct aim_rxcblist_s *cur; - - if (!conn) - return NULL; - - /* gaim_debug_misc("oscar", "aim_callhandler: calling for %04x/%04x\n", family, type); */ - - for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur; cur = cur->next) { - if ((cur->family == family) && (cur->type == type)) - return cur->handler; - } - - return NULL; -} - -faim_internal void aim_clonehandlers(OscarSession *sess, OscarConnection *dest, OscarConnection *src) -{ - struct aim_rxcblist_s *cur; - - for (cur = (struct aim_rxcblist_s *)src->handlerlist; cur; cur = cur->next) { - aim_conn_addhandler(sess, dest, cur->family, cur->type, - cur->handler, cur->flags); - } - - return; -} - -faim_internal int aim_callhandler_noparam(OscarSession *sess, OscarConnection *conn,guint16 family, guint16 type, FlapFrame *ptr) -{ - aim_rxcallback_t userfunc; - - if ((userfunc = aim_callhandler(sess, conn, family, type))) - return userfunc(sess, ptr); - - return 1; /* XXX */ -} - -/* - * aim_rxdispatch() - * - * Basically, heres what this should do: - * 1) Determine correct packet handler for this packet - * 2) Mark the packet handled (so it can be dequeued in purge_queue()) - * 3) Send the packet to the packet handler - * 4) Go to next packet in the queue and start over - * 5) When done, run purge_queue() to purge handled commands - * - * TODO: Clean up. - * TODO: More support for mid-level handlers. - * TODO: Allow for NULL handlers. - * - */ -faim_export void aim_rxdispatch(OscarSession *sess) -{ - int i; - FlapFrame *cur; - - for (cur = sess->queue_incoming, i = 0; cur; cur = cur->next, i++) { - - /* - * XXX: This is still fairly ugly. - */ - - if (cur->handled) - continue; - - if (cur->hdrtype == AIM_FRAMETYPE_FLAP) { - if (cur->hdr.flap.channel == 0x01) { - cur->handled = aim_callhandler_noparam(sess, cur->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, cur); /* XXX use consumenonsnac */ - continue; - - } else if (cur->hdr.flap.channel == 0x02) { - if ((cur->handled = consumesnac(sess, cur))) - continue; - - } else if (cur->hdr.flap.channel == 0x04) { - cur->handled = negchan_middle(sess, cur); - continue; - - } else if (cur->hdr.flap.channel == 0x05) { - - } - - } else if (cur->hdrtype == AIM_FRAMETYPE_OFT) { - if (cur->conn->type == AIM_CONN_TYPE_RENDEZVOUS) { - aim_rxdispatch_rendezvous(sess, cur); - cur->handled = 1; - continue; - - } else if (cur->conn->type == AIM_CONN_TYPE_LISTENER) { - /* not possible */ - gaim_debug_misc("oscar", "rxdispatch called on LISTENER connection!\n"); - cur->handled = 1; - continue; - } - } - - if (!cur->handled) { - consumenonsnac(sess, cur, 0xffff, 0xffff); /* last chance! */ - cur->handled = 1; - } - } - - /* - * This doesn't have to be called here. It could easily be done - * by a separate thread or something. It's an administrative operation, - * and can take a while. Though the less you call it the less memory - * you'll have :) - */ - aim_purge_rxqueue(sess); - - return; -} - -faim_internal int aim_parse_unknown(OscarSession *sess, FlapFrame *frame, ...) -{ - int i; - - gaim_debug_misc("oscar", "\nRecieved unknown packet:"); - - for (i = 0; aim_bstream_empty(&frame->data); i++) { - if ((i % 8) == 0) - gaim_debug_misc("oscar", "\n\t"); - - gaim_debug_misc("oscar", "0x%2x ", aimbs_get8(&frame->data)); - } - - gaim_debug_misc("oscar", "\n\n"); return 1; } +#endif
--- a/src/protocols/oscar/rxqueue.c Fri Apr 07 01:05:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,299 +0,0 @@ -/* - * 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 -*/ - -/* - * This file contains the management routines for the receive - * (incoming packet) queue. The actual packet handlers are in - * rxhandlers.c. - */ - -#include "oscar.h" - -#ifndef _WIN32 -#include <sys/socket.h> -#endif - -/* - * - */ -faim_internal int aim_recv(int fd, void *buf, size_t count) -{ - int left, cur; - - for (cur = 0, left = count; left; ) { - int ret; - - ret = recv(fd, ((unsigned char *)buf)+cur, left, 0); - - /* Of course EOF is an error, only morons disagree with that. */ - if (ret <= 0) - return -1; - - cur += ret; - left -= ret; - } - - return cur; -} - -/* - * Read into a byte stream. Will not read more than count, but may read - * less if there is not enough room in the stream buffer. - */ -faim_internal int aim_bstream_recv(ByteStream *bs, int fd, size_t count) -{ - int red = 0; - - if (!bs || (fd < 0)) - return -1; - - if (count > (bs->len - bs->offset)) - count = bs->len - bs->offset; /* truncate to remaining space */ - - if (count) { - - red = aim_recv(fd, bs->data + bs->offset, count); - - if (red <= 0) - return -1; - } - - bs->offset += red; - - return red; -} - -/** - * Free an FlapFrame - * - * @param frame The frame to free. - * @return -1 on error; 0 on success. - */ -faim_internal void aim_frame_destroy(FlapFrame *frame) -{ - - free(frame->data.data); /* XXX aim_bstream_free */ - free(frame); - - return; -} - -/* - * Read a FLAP header from conn into fr, and return the number of - * bytes in the payload. - * - * @return -1 on error, otherwise return the length of the payload. - */ -static int aim_get_command_flap(OscarSession *sess, OscarConnection *conn, FlapFrame *fr) -{ - guint8 hdr_raw[6]; - ByteStream hdr; - - fr->hdrtype = AIM_FRAMETYPE_FLAP; - - /* - * Read FLAP header. Six bytes total. - * - * Byte # | Description - * -------|------------- - * 0x00 | Always 0x2a - * 0x01 | Channel number, usually "2." "1" is used during login, - * | 4 is used during logoff. - * 0x02 | Sequence number, 2 bytes. - * 0x04 | Number of data bytes that follow, 2 bytes. - */ - aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); - if (aim_bstream_recv(&hdr, conn->fd, 6) < 6) { - aim_conn_close(sess, conn); - return -1; - } - - aim_bstream_rewind(&hdr); - - /* - * This shouldn't happen unless the socket breaks, the server breaks, - * or we break. We must handle it just in case. - */ - if (aimbs_get8(&hdr) != 0x2a) { - gaim_debug_misc("oscar", "Invalid FLAP frame received on FLAP connection!"); - aim_conn_close(sess, conn); - return -1; - } - - fr->hdr.flap.channel = aimbs_get8(&hdr); - fr->hdr.flap.seqnum = aimbs_get16(&hdr); - - return aimbs_get16(&hdr); -} - -/* - * Read a rendezvous header from conn into fr, and return the number of - * bytes in the payload. - * - * @return -1 on error, otherwise return the length of the payload. - */ -static int aim_get_command_rendezvous(OscarSession *sess, OscarConnection *conn, FlapFrame *fr) -{ - guint8 hdr_raw[8]; - ByteStream hdr; - - fr->hdrtype = AIM_FRAMETYPE_OFT; - - /* - * Read rendezvous header - */ - aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); - if (aim_bstream_recv(&hdr, conn->fd, 8) < 8) { - aim_conn_close(sess, conn); - return -1; - } - - aim_bstream_rewind(&hdr); - - aimbs_getrawbuf(&hdr, fr->hdr.rend.magic, 4); - fr->hdr.rend.hdrlen = aimbs_get16(&hdr); - fr->hdr.rend.type = aimbs_get16(&hdr); - - return fr->hdr.rend.hdrlen - 8; -} - -/* - * Grab a single command sequence off the socket, and enqueue it in - * the incoming event queue in a separate struct. - * - * @return 0 on success, otherwise return the error number. - * "Success" doesn't mean we have new data, it just means - * the connection isn't dead. - */ -faim_export int aim_get_command(OscarSession *sess, OscarConnection *conn) -{ - FlapFrame *fr; - int payloadlen; - - if (!sess || !conn) - return -EINVAL; - - if (conn->fd == -1) - return -1; /* it's an aim_conn_close()'d connection */ - - /* If stdin is closed, then zero becomes a valid fd - if (conn->fd < 3) - return -1; - */ - - if (conn->status & AIM_CONN_STATUS_INPROGRESS) - return aim_conn_completeconnect(sess, conn); - - if (!(fr = (FlapFrame *)calloc(sizeof(FlapFrame), 1))) - return -ENOMEM; - - /* - * Rendezvous (client to client) connections do not speak FLAP, so this - * function will break on them. - */ - if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) - payloadlen = aim_get_command_rendezvous(sess, conn, fr); - else if (conn->type == AIM_CONN_TYPE_LISTENER) { - gaim_debug_misc("oscar", "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd); - free(fr); - return -1; - } else - payloadlen = aim_get_command_flap(sess, conn, fr); - - if (payloadlen < 0) { - free(fr); - return -1; - } - - if (payloadlen > 0) { - guint8 *payload = NULL; - - if (!(payload = (guint8 *) malloc(payloadlen))) { - aim_frame_destroy(fr); - return -1; - } - - aim_bstream_init(&fr->data, payload, payloadlen); - - /* read the payload */ - if (aim_bstream_recv(&fr->data, conn->fd, payloadlen) < payloadlen) { - aim_frame_destroy(fr); /* free's payload */ - aim_conn_close(sess, conn); - return -1; - } - } else - aim_bstream_init(&fr->data, NULL, 0); - - aim_bstream_rewind(&fr->data); - - fr->conn = conn; - - /* Enqueue this puppy */ - fr->next = NULL; /* this will always be at the bottom */ - if (sess->queue_incoming == NULL) - sess->queue_incoming = fr; - else { - FlapFrame *cur; - for (cur = sess->queue_incoming; cur->next; cur = cur->next); - cur->next = fr; - } - - fr->conn->lastactivity = time(NULL); - - return 0; -} - -/* - * Purge receive queue of all handled commands (->handled==1). - * - */ -faim_export void aim_purge_rxqueue(OscarSession *sess) -{ - FlapFrame *cur, **prev; - - for (prev = &sess->queue_incoming; (cur = *prev); ) { - if (cur->handled) { - *prev = cur->next; - aim_frame_destroy(cur); - } else - prev = &cur->next; - } - - return; -} - -/* - * Since aim_get_command will oscar_connection_destroy dead connections, we need - * to clean up the rxqueue of unprocessed connections on that socket. - * - * XXX: this is something that was handled better in the old connection - * handling method, but eh. - */ -faim_internal void aim_rxqueue_cleanbyconn(OscarSession *sess, OscarConnection *conn) -{ - FlapFrame *currx; - - for (currx = sess->queue_incoming; currx; currx = currx->next) { - if ((!currx->handled) && (currx->conn == conn)) - currx->handled = 1; - } - - return; -}
--- a/src/protocols/oscar/session.c Fri Apr 07 01:05:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/* - * 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 -*/ - -#include "oscar.h" - -/** - * Allocates a new OscarSession and initializes it with default values. - */ -OscarSession * -oscar_session_new(void) -{ - OscarSession *sess; - - sess = g_new0(OscarSession, 1); - - aim_initsnachash(sess); - sess->snacid_next = 0x00000001; - - /* - * This must always be set. Default to the queue-based - * version for back-compatibility. - */ - aim_tx_setenqueue(sess, AIM_TX_QUEUED, NULL); - - /* - * Register all the modules for this session... - */ - aim__registermodule(sess, misc_modfirst); /* load the catch-all first */ - aim__registermodule(sess, service_modfirst); - aim__registermodule(sess, locate_modfirst); - aim__registermodule(sess, buddylist_modfirst); - aim__registermodule(sess, msg_modfirst); - aim__registermodule(sess, adverts_modfirst); - aim__registermodule(sess, invite_modfirst); - aim__registermodule(sess, admin_modfirst); - aim__registermodule(sess, popups_modfirst); - aim__registermodule(sess, bos_modfirst); - aim__registermodule(sess, search_modfirst); - aim__registermodule(sess, stats_modfirst); - aim__registermodule(sess, translate_modfirst); - aim__registermodule(sess, chatnav_modfirst); - aim__registermodule(sess, chat_modfirst); - aim__registermodule(sess, odir_modfirst); - aim__registermodule(sess, bart_modfirst); - /* missing 0x11 - 0x12 */ - aim__registermodule(sess, ssi_modfirst); - /* missing 0x14 */ - aim__registermodule(sess, icq_modfirst); - /* missing 0x16 */ - aim__registermodule(sess, auth_modfirst); - aim__registermodule(sess, email_modfirst); - - return sess; -} - -/** - * Logoff and deallocate a session. - * - * @param sess Session to kill - */ -void -oscar_session_destroy(OscarSession *sess) -{ - aim_cleansnacs(sess, -1); - - while (sess->oscar_connections != NULL) - oscar_connection_destroy(sess, sess->oscar_connections->data); - - aim__shutdownmodules(sess); - - g_free(sess); -}
--- a/src/protocols/oscar/snac.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/snac.c Fri Apr 07 05:10:56 2006 +0000 @@ -37,21 +37,21 @@ /* * Called from oscar_session_new() to initialize the hash. */ -faim_internal void aim_initsnachash(OscarSession *sess) +void aim_initsnachash(OscarData *od) { int i; for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) - sess->snac_hash[i] = NULL; + od->snac_hash[i] = NULL; return; } -faim_internal aim_snacid_t aim_cachesnac(OscarSession *sess, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen) +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 = sess->snacid_next++; + snac.id = od->snacid_next++; snac.family = family; snac.type = type; snac.flags = flags; @@ -63,14 +63,14 @@ } else snac.data = NULL; - return aim_newsnac(sess, &snac); + return aim_newsnac(od, &snac); } /* * Clones the passed snac structure and caches it in the * list/hash. */ -faim_internal aim_snacid_t aim_newsnac(OscarSession *sess, aim_snac_t *newsnac) +aim_snacid_t aim_newsnac(OscarData *od, aim_snac_t *newsnac) { aim_snac_t *snac; int index; @@ -85,27 +85,27 @@ index = snac->id % FAIM_SNAC_HASH_SIZE; - snac->next = (aim_snac_t *)sess->snac_hash[index]; - sess->snac_hash[index] = (void *)snac; + 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, + * 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. * */ -faim_internal aim_snac_t *aim_remsnac(OscarSession *sess, aim_snacid_t id) +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 **)&sess->snac_hash[index]; (cur = *prev); ) { + for (prev = (aim_snac_t **)&od->snac_hash[index]; (cur = *prev); ) { if (cur->id == id) { *prev = cur->next; if (cur->flags & AIM_SNACFLAGS_DESTRUCTOR) { @@ -127,7 +127,7 @@ * maxage is the _minimum_ age in seconds to keep SNACs. * */ -faim_export void aim_cleansnacs(OscarSession *sess, int maxage) +void aim_cleansnacs(OscarData *od, int maxage) { int i; @@ -135,12 +135,12 @@ aim_snac_t *cur, **prev; time_t curtime; - if (!sess->snac_hash[i]) + if (!od->snac_hash[i]) continue; curtime = time(NULL); /* done here in case we waited for the lock */ - for (prev = (aim_snac_t **)&sess->snac_hash[i]; (cur = *prev); ) { + for (prev = (aim_snac_t **)&od->snac_hash[i]; (cur = *prev); ) { if ((curtime - cur->issuetime) > maxage) { *prev = cur->next; @@ -155,13 +155,13 @@ return; } -faim_internal int aim_putsnac(ByteStream *bs, guint16 family, guint16 subtype, guint16 flags, aim_snacid_t snacid) +int aim_putsnac(ByteStream *bs, guint16 family, guint16 subtype, guint16 flags, aim_snacid_t snacid) { - aimbs_put16(bs, family); - aimbs_put16(bs, subtype); - aimbs_put16(bs, flags); - aimbs_put32(bs, snacid); + byte_stream_put16(bs, family); + byte_stream_put16(bs, subtype); + byte_stream_put16(bs, flags); + byte_stream_put32(bs, snacid); return 10; }
--- a/src/protocols/oscar/snactypes.h Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/snactypes.h Fri Apr 07 05:10:56 2006 +0000 @@ -28,26 +28,26 @@ /* * SNAC Families. */ -#define OSCAR_FAMILY_OSERVICE 0x0001 -#define OSCAR_FAMILY_LOCATE 0x0002 -#define OSCAR_FAMILY_BUDDY 0x0003 -#define OSCAR_FAMILY_ICBM 0x0004 -#define OSCAR_FAMILY_ADVERT 0x0005 -#define OSCAR_FAMILY_INVITE 0x0006 -#define OSCAR_FAMILY_ADMIN 0x0007 -#define OSCAR_FAMILY_POPUP 0x0008 -#define OSCAR_FAMILY_BOS 0x0009 -#define OSCAR_FAMILY_USERLOOKUP 0x000a -#define OSCAR_FAMILY_STATS 0x000b -#define OSCAR_FAMILY_TRANSLATE 0x000c -#define OSCAR_FAMILY_CHATNAV 0x000d -#define OSCAR_FAMILY_CHAT 0x000e -#define OSCAR_FAMILY_ODIR 0x000f -#define OSCAR_FAMILY_BART 0x0010 -#define OSCAR_FAMILY_FEEDBAG 0x0013 -#define OSCAR_FAMILY_ICQ 0x0015 -#define OSCAR_FAMILY_AUTH 0x0017 -#define OSCAR_FAMILY_ALERT 0x0018 +#define SNAC_FAMILY_OSERVICE 0x0001 +#define SNAC_FAMILY_LOCATE 0x0002 +#define SNAC_FAMILY_BUDDY 0x0003 +#define SNAC_FAMILY_ICBM 0x0004 +#define SNAC_FAMILY_ADVERT 0x0005 +#define SNAC_FAMILY_INVITE 0x0006 +#define SNAC_FAMILY_ADMIN 0x0007 +#define SNAC_FAMILY_POPUP 0x0008 +#define SNAC_FAMILY_BOS 0x0009 +#define SNAC_FAMILY_USERLOOKUP 0x000a +#define SNAC_FAMILY_STATS 0x000b +#define SNAC_FAMILY_TRANSLATE 0x000c +#define SNAC_FAMILY_CHATNAV 0x000d +#define SNAC_FAMILY_CHAT 0x000e +#define SNAC_FAMILY_ODIR 0x000f +#define SNAC_FAMILY_BART 0x0010 +#define SNAC_FAMILY_FEEDBAG 0x0013 +#define SNAC_FAMILY_ICQ 0x0015 +#define SNAC_FAMILY_AUTH 0x0017 +#define SNAC_FAMILY_ALERT 0x0018 #define AIM_CB_FAM_SPECIAL 0xffff /* Internal libfaim use */ @@ -63,191 +63,190 @@ /* * SNAC Family: General. */ -#define OSCAR_SUBTYPE_OSERVICE_ERROR 0x0001 -#define OSCAR_SUBTYPE_OSERVICE_CLIENTREADY 0x0002 -#define OSCAR_SUBTYPE_OSERVICE_SERVERREADY 0x0003 -#define OSCAR_SUBTYPE_OSERVICE_SERVICEREQ 0x0004 -#define OSCAR_SUBTYPE_OSERVICE_REDIRECT 0x0005 -#define OSCAR_SUBTYPE_OSERVICE_RATEINFOREQ 0x0006 -#define OSCAR_SUBTYPE_OSERVICE_RATEINFO 0x0007 -#define OSCAR_SUBTYPE_OSERVICE_RATEINFOACK 0x0008 -#define OSCAR_SUBTYPE_OSERVICE_RATECHANGE 0x000a -#define OSCAR_SUBTYPE_OSERVICE_SERVERPAUSE 0x000b -#define OSCAR_SUBTYPE_OSERVICE_SERVERRESUME 0x000d -#define OSCAR_SUBTYPE_OSERVICE_REQSELFINFO 0x000e -#define OSCAR_SUBTYPE_OSERVICE_SELFINFO 0x000f -#define OSCAR_SUBTYPE_OSERVICE_EVIL 0x0010 -#define OSCAR_SUBTYPE_OSERVICE_SETIDLE 0x0011 -#define OSCAR_SUBTYPE_OSERVICE_MIGRATIONREQ 0x0012 -#define OSCAR_SUBTYPE_OSERVICE_MOTD 0x0013 -#define OSCAR_SUBTYPE_OSERVICE_SETPRIVFLAGS 0x0014 -#define OSCAR_SUBTYPE_OSERVICE_WELLKNOWNURL 0x0015 -#define OSCAR_SUBTYPE_OSERVICE_NOP 0x0016 -#define OSCAR_SUBTYPE_OSERVICE_DEFAULT 0xffff +#define SNAC_SUBTYPE_OSERVICE_ERROR 0x0001 +#define SNAC_SUBTYPE_OSERVICE_CLIENTREADY 0x0002 +#define SNAC_SUBTYPE_OSERVICE_SERVERREADY 0x0003 +#define SNAC_SUBTYPE_OSERVICE_SERVICEREQ 0x0004 +#define SNAC_SUBTYPE_OSERVICE_REDIRECT 0x0005 +#define SNAC_SUBTYPE_OSERVICE_RATEINFOREQ 0x0006 +#define SNAC_SUBTYPE_OSERVICE_RATEINFO 0x0007 +#define SNAC_SUBTYPE_OSERVICE_RATEINFOACK 0x0008 +#define SNAC_SUBTYPE_OSERVICE_RATECHANGE 0x000a +#define SNAC_SUBTYPE_OSERVICE_SERVERPAUSE 0x000b +#define SNAC_SUBTYPE_OSERVICE_SERVERRESUME 0x000d +#define SNAC_SUBTYPE_OSERVICE_REQSELFINFO 0x000e +#define SNAC_SUBTYPE_OSERVICE_SELFINFO 0x000f +#define SNAC_SUBTYPE_OSERVICE_EVIL 0x0010 +#define SNAC_SUBTYPE_OSERVICE_SETIDLE 0x0011 +#define SNAC_SUBTYPE_OSERVICE_MIGRATIONREQ 0x0012 +#define SNAC_SUBTYPE_OSERVICE_MOTD 0x0013 +#define SNAC_SUBTYPE_OSERVICE_SETPRIVFLAGS 0x0014 +#define SNAC_SUBTYPE_OSERVICE_WELLKNOWNURL 0x0015 +#define SNAC_SUBTYPE_OSERVICE_NOP 0x0016 +#define SNAC_SUBTYPE_OSERVICE_DEFAULT 0xffff /* * SNAC Family: Location Services. */ -#define OSCAR_SUBTYPE_LOCATE_ERROR 0x0001 -#define OSCAR_SUBTYPE_LOCATE_REQRIGHTS 0x0002 -#define OSCAR_SUBTYPE_LOCATE_RIGHTSINFO 0x0003 -#define OSCAR_SUBTYPE_LOCATE_SETUSERINFO 0x0004 -#define OSCAR_SUBTYPE_LOCATE_REQUSERINFO 0x0005 -#define OSCAR_SUBTYPE_LOCATE_USERINFO 0x0006 -#define OSCAR_SUBTYPE_LOCATE_WATCHERSUBREQ 0x0007 -#define OSCAR_SUBTYPE_LOCATE_WATCHERNOT 0x0008 -#define OSCAR_SUBTYPE_LOCATE_GOTINFOBLOCK 0xfffd -#define OSCAR_SUBTYPE_LOCATE_REQUESTINFOTIMEOUT 0xfffe -#define OSCAR_SUBTYPE_LOCATE_DEFAULT 0xffff +#define SNAC_SUBTYPE_LOCATE_ERROR 0x0001 +#define SNAC_SUBTYPE_LOCATE_REQRIGHTS 0x0002 +#define SNAC_SUBTYPE_LOCATE_RIGHTSINFO 0x0003 +#define SNAC_SUBTYPE_LOCATE_SETUSERINFO 0x0004 +#define SNAC_SUBTYPE_LOCATE_REQUSERINFO 0x0005 +#define SNAC_SUBTYPE_LOCATE_USERINFO 0x0006 +#define SNAC_SUBTYPE_LOCATE_WATCHERSUBREQ 0x0007 +#define SNAC_SUBTYPE_LOCATE_WATCHERNOT 0x0008 +#define SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK 0xfffd +#define SNAC_SUBTYPE_LOCATE_DEFAULT 0xffff /* * SNAC Family: Buddy List Management Services. */ -#define OSCAR_SUBTYPE_BUDDY_ERROR 0x0001 -#define OSCAR_SUBTYPE_BUDDY_REQRIGHTS 0x0002 -#define OSCAR_SUBTYPE_BUDDY_RIGHTSINFO 0x0003 -#define OSCAR_SUBTYPE_BUDDY_ADDBUDDY 0x0004 -#define OSCAR_SUBTYPE_BUDDY_REMBUDDY 0x0005 -#define OSCAR_SUBTYPE_BUDDY_REJECT 0x000a -#define OSCAR_SUBTYPE_BUDDY_ONCOMING 0x000b -#define OSCAR_SUBTYPE_BUDDY_OFFGOING 0x000c -#define OSCAR_SUBTYPE_BUDDY_DEFAULT 0xffff +#define SNAC_SUBTYPE_BUDDY_ERROR 0x0001 +#define SNAC_SUBTYPE_BUDDY_REQRIGHTS 0x0002 +#define SNAC_SUBTYPE_BUDDY_RIGHTSINFO 0x0003 +#define SNAC_SUBTYPE_BUDDY_ADDBUDDY 0x0004 +#define SNAC_SUBTYPE_BUDDY_REMBUDDY 0x0005 +#define SNAC_SUBTYPE_BUDDY_REJECT 0x000a +#define SNAC_SUBTYPE_BUDDY_ONCOMING 0x000b +#define SNAC_SUBTYPE_BUDDY_OFFGOING 0x000c +#define SNAC_SUBTYPE_BUDDY_DEFAULT 0xffff /* * SNAC Family: Messaging Services. */ -#define OSCAR_SUBTYPE_ICBM_ERROR 0x0001 -#define OSCAR_SUBTYPE_ICBM_PARAMINFO 0x0005 -#define OSCAR_SUBTYPE_ICBM_INCOMING 0x0007 -#define OSCAR_SUBTYPE_ICBM_EVIL 0x0009 -#define OSCAR_SUBTYPE_ICBM_MISSEDCALL 0x000a -#define OSCAR_SUBTYPE_ICBM_CLIENTAUTORESP 0x000b -#define OSCAR_SUBTYPE_ICBM_ACK 0x000c -#define OSCAR_SUBTYPE_ICBM_MTN 0x0014 -#define OSCAR_SUBTYPE_ICBM_DEFAULT 0xffff +#define SNAC_SUBTYPE_ICBM_ERROR 0x0001 +#define SNAC_SUBTYPE_ICBM_PARAMINFO 0x0005 +#define SNAC_SUBTYPE_ICBM_INCOMING 0x0007 +#define SNAC_SUBTYPE_ICBM_EVIL 0x0009 +#define SNAC_SUBTYPE_ICBM_MISSEDCALL 0x000a +#define SNAC_SUBTYPE_ICBM_CLIENTAUTORESP 0x000b +#define SNAC_SUBTYPE_ICBM_ACK 0x000c +#define SNAC_SUBTYPE_ICBM_MTN 0x0014 +#define SNAC_SUBTYPE_ICBM_DEFAULT 0xffff /* * SNAC Family: Advertisement Services */ -#define OSCAR_SUBTYPE_ADVERT_ERROR 0x0001 -#define OSCAR_SUBTYPE_ADVERT_DEFAULT 0xffff +#define SNAC_SUBTYPE_ADVERT_ERROR 0x0001 +#define SNAC_SUBTYPE_ADVERT_DEFAULT 0xffff /* * SNAC Family: Invitation Services. */ -#define OSCAR_SUBTYPE_INVITE_ERROR 0x0001 -#define OSCAR_SUBTYPE_INVITE_DEFAULT 0xffff +#define SNAC_SUBTYPE_INVITE_ERROR 0x0001 +#define SNAC_SUBTYPE_INVITE_DEFAULT 0xffff /* * SNAC Family: Administrative Services. */ -#define OSCAR_SUBTYPE_ADMIN_ERROR 0x0001 -#define OSCAR_SUBTYPE_ADMIN_INFOCHANGE_REPLY 0x0005 -#define OSCAR_SUBTYPE_ADMIN_DEFAULT 0xffff +#define SNAC_SUBTYPE_ADMIN_ERROR 0x0001 +#define SNAC_SUBTYPE_ADMIN_INFOCHANGE_REPLY 0x0005 +#define SNAC_SUBTYPE_ADMIN_DEFAULT 0xffff /* * SNAC Family: Popup Messages */ -#define OSCAR_SUBTYPE_POPUP_ERROR 0x0001 -#define OSCAR_SUBTYPE_POPUP_DEFAULT 0xffff +#define SNAC_SUBTYPE_POPUP_ERROR 0x0001 +#define SNAC_SUBTYPE_POPUP_DEFAULT 0xffff /* * SNAC Family: Misc BOS Services. */ -#define OSCAR_SUBTYPE_BOS_ERROR 0x0001 -#define OSCAR_SUBTYPE_BOS_RIGHTSQUERY 0x0002 -#define OSCAR_SUBTYPE_BOS_RIGHTS 0x0003 -#define OSCAR_SUBTYPE_BOS_DEFAULT 0xffff +#define SNAC_SUBTYPE_BOS_ERROR 0x0001 +#define SNAC_SUBTYPE_BOS_RIGHTSQUERY 0x0002 +#define SNAC_SUBTYPE_BOS_RIGHTS 0x0003 +#define SNAC_SUBTYPE_BOS_DEFAULT 0xffff /* * SNAC Family: User Lookup Services */ -#define OSCAR_SUBTYPE_USERLOOKUP_ERROR 0x0001 -#define OSCAR_SUBTYPE_USERLOOKUP_DEFAULT 0xffff +#define SNAC_SUBTYPE_USERLOOKUP_ERROR 0x0001 +#define SNAC_SUBTYPE_USERLOOKUP_DEFAULT 0xffff /* * SNAC Family: User Status Services */ -#define OSCAR_SUBTYPE_STATS_ERROR 0x0001 -#define OSCAR_SUBTYPE_STATS_SETREPORTINTERVAL 0x0002 -#define OSCAR_SUBTYPE_STATS_REPORTACK 0x0004 -#define OSCAR_SUBTYPE_STATS_DEFAULT 0xffff +#define SNAC_SUBTYPE_STATS_ERROR 0x0001 +#define SNAC_SUBTYPE_STATS_SETREPORTINTERVAL 0x0002 +#define SNAC_SUBTYPE_STATS_REPORTACK 0x0004 +#define SNAC_SUBTYPE_STATS_DEFAULT 0xffff /* * SNAC Family: Translation Services */ -#define OSCAR_SUBTYPE_TRANSLATE_ERROR 0x0001 -#define OSCAR_SUBTYPE_TRANSLATE_DEFAULT 0xffff +#define SNAC_SUBTYPE_TRANSLATE_ERROR 0x0001 +#define SNAC_SUBTYPE_TRANSLATE_DEFAULT 0xffff /* * SNAC Family: Chat Navigation Services */ -#define OSCAR_SUBTYPE_CHATNAV_ERROR 0x0001 -#define OSCAR_SUBTYPE_CHATNAV_CREATE 0x0008 -#define OSCAR_SUBTYPE_CHATNAV_INFO 0x0009 -#define OSCAR_SUBTYPE_CHATNAV_DEFAULT 0xffff +#define SNAC_SUBTYPE_CHATNAV_ERROR 0x0001 +#define SNAC_SUBTYPE_CHATNAV_CREATE 0x0008 +#define SNAC_SUBTYPE_CHATNAV_INFO 0x0009 +#define SNAC_SUBTYPE_CHATNAV_DEFAULT 0xffff /* * SNAC Family: Chat Services */ -#define OSCAR_SUBTYPE_CHAT_ERROR 0x0001 -#define OSCAR_SUBTYPE_CHAT_ROOMINFOUPDATE 0x0002 -#define OSCAR_SUBTYPE_CHAT_USERJOIN 0x0003 -#define OSCAR_SUBTYPE_CHAT_USERLEAVE 0x0004 -#define OSCAR_SUBTYPE_CHAT_OUTGOINGMSG 0x0005 -#define OSCAR_SUBTYPE_CHAT_INCOMINGMSG 0x0006 -#define OSCAR_SUBTYPE_CHAT_DEFAULT 0xffff +#define SNAC_SUBTYPE_CHAT_ERROR 0x0001 +#define SNAC_SUBTYPE_CHAT_ROOMINFOUPDATE 0x0002 +#define SNAC_SUBTYPE_CHAT_USERJOIN 0x0003 +#define SNAC_SUBTYPE_CHAT_USERLEAVE 0x0004 +#define SNAC_SUBTYPE_CHAT_OUTGOINGMSG 0x0005 +#define SNAC_SUBTYPE_CHAT_INCOMINGMSG 0x0006 +#define SNAC_SUBTYPE_CHAT_DEFAULT 0xffff /* * SNAC Family: "New" Search */ -#define OSCAR_SUBTYPE_ODIR_ERROR 0x0001 -#define OSCAR_SUBTYPE_ODIR_SEARCH 0x0002 -#define OSCAR_SUBTYPE_ODIR_RESULTS 0x0003 +#define SNAC_SUBTYPE_ODIR_ERROR 0x0001 +#define SNAC_SUBTYPE_ODIR_SEARCH 0x0002 +#define SNAC_SUBTYPE_ODIR_RESULTS 0x0003 /* * SNAC Family: Buddy icons */ -#define OSCAR_SUBTYPE_BART_ERROR 0x0001 -#define OSCAR_SUBTYPE_BART_REQUEST 0x0004 -#define OSCAR_SUBTYPE_BART_RESPONSE 0x0005 +#define SNAC_SUBTYPE_BART_ERROR 0x0001 +#define SNAC_SUBTYPE_BART_REQUEST 0x0004 +#define SNAC_SUBTYPE_BART_RESPONSE 0x0005 /* * SNAC Family: Server-Stored Buddy Lists */ -#define OSCAR_SUBTYPE_FEEDBAG_ERROR 0x0001 -#define OSCAR_SUBTYPE_FEEDBAG_REQRIGHTS 0x0002 -#define OSCAR_SUBTYPE_FEEDBAG_RIGHTSINFO 0x0003 -#define OSCAR_SUBTYPE_FEEDBAG_REQDATA 0x0004 -#define OSCAR_SUBTYPE_FEEDBAG_REQIFCHANGED 0x0005 -#define OSCAR_SUBTYPE_FEEDBAG_LIST 0x0006 -#define OSCAR_SUBTYPE_FEEDBAG_ACTIVATE 0x0007 -#define OSCAR_SUBTYPE_FEEDBAG_ADD 0x0008 -#define OSCAR_SUBTYPE_FEEDBAG_MOD 0x0009 -#define OSCAR_SUBTYPE_FEEDBAG_DEL 0x000A -#define OSCAR_SUBTYPE_FEEDBAG_SRVACK 0x000E -#define OSCAR_SUBTYPE_FEEDBAG_NOLIST 0x000F -#define OSCAR_SUBTYPE_FEEDBAG_EDITSTART 0x0011 -#define OSCAR_SUBTYPE_FEEDBAG_EDITSTOP 0x0012 -#define OSCAR_SUBTYPE_FEEDBAG_SENDAUTH 0x0014 -#define OSCAR_SUBTYPE_FEEDBAG_RECVAUTH 0x0015 -#define OSCAR_SUBTYPE_FEEDBAG_SENDAUTHREQ 0x0018 -#define OSCAR_SUBTYPE_FEEDBAG_RECVAUTHREQ 0x0019 -#define OSCAR_SUBTYPE_FEEDBAG_SENDAUTHREP 0x001a -#define OSCAR_SUBTYPE_FEEDBAG_RECVAUTHREP 0x001b -#define OSCAR_SUBTYPE_FEEDBAG_ADDED 0x001c +#define SNAC_SUBTYPE_FEEDBAG_ERROR 0x0001 +#define SNAC_SUBTYPE_FEEDBAG_REQRIGHTS 0x0002 +#define SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO 0x0003 +#define SNAC_SUBTYPE_FEEDBAG_REQDATA 0x0004 +#define SNAC_SUBTYPE_FEEDBAG_REQIFCHANGED 0x0005 +#define SNAC_SUBTYPE_FEEDBAG_LIST 0x0006 +#define SNAC_SUBTYPE_FEEDBAG_ACTIVATE 0x0007 +#define SNAC_SUBTYPE_FEEDBAG_ADD 0x0008 +#define SNAC_SUBTYPE_FEEDBAG_MOD 0x0009 +#define SNAC_SUBTYPE_FEEDBAG_DEL 0x000A +#define SNAC_SUBTYPE_FEEDBAG_SRVACK 0x000E +#define SNAC_SUBTYPE_FEEDBAG_NOLIST 0x000F +#define SNAC_SUBTYPE_FEEDBAG_EDITSTART 0x0011 +#define SNAC_SUBTYPE_FEEDBAG_EDITSTOP 0x0012 +#define SNAC_SUBTYPE_FEEDBAG_SENDAUTH 0x0014 +#define SNAC_SUBTYPE_FEEDBAG_RECVAUTH 0x0015 +#define SNAC_SUBTYPE_FEEDBAG_SENDAUTHREQ 0x0018 +#define SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ 0x0019 +#define SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP 0x001a +#define SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP 0x001b +#define SNAC_SUBTYPE_FEEDBAG_ADDED 0x001c /* * SNAC Family: ICQ * * Most of these are actually special. */ -#define OSCAR_SUBTYPE_ICQ_ERROR 0x0001 -#define OSCAR_SUBTYPE_ICQ_OFFLINEMSG 0x00f0 -#define OSCAR_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE 0x00f1 -#define OSCAR_SUBTYPE_ICQ_INFO 0x00f2 -#define OSCAR_SUBTYPE_ICQ_ALIAS 0x00f3 -#define OSCAR_SUBTYPE_ICQ_DEFAULT 0xffff +#define SNAC_SUBTYPE_ICQ_ERROR 0x0001 +#define SNAC_SUBTYPE_ICQ_OFFLINEMSG 0x00f0 +#define SNAC_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE 0x00f1 +#define SNAC_SUBTYPE_ICQ_INFO 0x00f2 +#define SNAC_SUBTYPE_ICQ_ALIAS 0x00f3 +#define SNAC_SUBTYPE_ICQ_DEFAULT 0xffff /* * SNAC Family: Authorizer @@ -255,13 +254,13 @@ * Used only in protocol versions three and above. * */ -#define OSCAR_SUBTYPE_AUTH_ERROR 0x0001 -#define OSCAR_SUBTYPE_AUTH_LOGINREQEST 0x0002 -#define OSCAR_SUBTYPE_AUTH_LOGINRESPONSE 0x0003 -#define OSCAR_SUBTYPE_AUTH_AUTHREQ 0x0006 -#define OSCAR_SUBTYPE_AUTH_AUTHRESPONSE 0x0007 -#define OSCAR_SUBTYPE_AUTH_SECURID_REQUEST 0x000a -#define OSCAR_SUBTYPE_AUTH_SECURID_RESPONSE 0x000b +#define SNAC_SUBTYPE_AUTH_ERROR 0x0001 +#define SNAC_SUBTYPE_AUTH_LOGINREQEST 0x0002 +#define SNAC_SUBTYPE_AUTH_LOGINRESPONSE 0x0003 +#define SNAC_SUBTYPE_AUTH_AUTHREQ 0x0006 +#define SNAC_SUBTYPE_AUTH_AUTHRESPONSE 0x0007 +#define SNAC_SUBTYPE_AUTH_SECURID_REQUEST 0x000a +#define SNAC_SUBTYPE_AUTH_SECURID_RESPONSE 0x000b /* * SNAC Family: Email @@ -270,10 +269,10 @@ * associated with your screen name. * */ -#define OSCAR_SUBTYPE_ALERT_ERROR 0x0001 -#define OSCAR_SUBTYPE_ALERT_SENDCOOKIES 0x0006 -#define OSCAR_SUBTYPE_ALERT_MAILSTATUS 0x0007 -#define OSCAR_SUBTYPE_ALERT_INIT 0x0016 +#define SNAC_SUBTYPE_ALERT_ERROR 0x0001 +#define SNAC_SUBTYPE_ALERT_SENDCOOKIES 0x0006 +#define SNAC_SUBTYPE_ALERT_MAILSTATUS 0x0007 +#define SNAC_SUBTYPE_ALERT_INIT 0x0016 /* * SNAC Family: Internal Messages @@ -284,9 +283,7 @@ * */ #define AIM_CB_SPECIAL_CONNERR 0x0003 -#define AIM_CB_SPECIAL_FLAPVER 0x0005 #define AIM_CB_SPECIAL_CONNINITDONE 0x0006 -#define AIM_CB_SPECIAL_IMAGETRANSFER 0x0007 /* SNAC flags */ #define AIM_SNACFLAGS_DESTRUCTOR 0x0001
--- a/src/protocols/oscar/tlv.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/tlv.c Fri Apr 07 05:10:56 2006 +0000 @@ -21,12 +21,12 @@ #include "oscar.h" -static aim_tlv_t *createtlv(guint16 type, guint16 length, guint8 *value) +static aim_tlv_t * +createtlv(guint16 type, guint16 length, guint8 *value) { aim_tlv_t *ret; - if (!(ret = (aim_tlv_t *)malloc(sizeof(aim_tlv_t)))) - return NULL; + ret = g_new(aim_tlv_t, 1); ret->type = type; ret->length = length; ret->value = value; @@ -34,7 +34,8 @@ return ret; } -static void freetlv(aim_tlv_t **oldtlv) +static void +freetlv(aim_tlv_t **oldtlv) { if (!oldtlv || !*oldtlv) @@ -56,7 +57,7 @@ * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain - * bstream references, so that at least the ->value portion of each + * bstream references, so that at least the ->value portion of each * element doesn't need to be malloc/memcpy'd. This could prove to be * just as efficient as the in-place TLV parsing used in a couple places * in libfaim. @@ -64,21 +65,21 @@ * @param bs Input bstream * @return Return the TLV chain read */ -faim_internal aim_tlvlist_t *aim_tlvlist_read(ByteStream *bs) +aim_tlvlist_t *aim_tlvlist_read(ByteStream *bs) { aim_tlvlist_t *list = NULL, *cur; - while (aim_bstream_empty(bs) > 0) { + while (byte_stream_empty(bs) > 0) { guint16 type, length; - type = aimbs_get16(bs); - length = aimbs_get16(bs); + type = byte_stream_get16(bs); + length = byte_stream_get16(bs); #if 0 /* temporarily disabled until I know if they're still doing it or not */ /* * Okay, so now AOL has decided that any TLV of * type 0x0013 can only be two bytes, despite - * what the actual given length is. So here + * what the actual given length is. So here * we dump any invalid TLVs of that sort. Hopefully * there's no special cases to this special case. * - mid (30jun2000) @@ -91,27 +92,15 @@ #endif else { - if (length > aim_bstream_empty(bs)) { - aim_tlvlist_free(&list); - return NULL; - } - - cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t)); - if (!cur) { + if (length > byte_stream_empty(bs)) { aim_tlvlist_free(&list); return NULL; } - memset(cur, 0, sizeof(aim_tlvlist_t)); - + cur = g_new0(aim_tlvlist_t, 1); cur->tlv = createtlv(type, length, NULL); - if (!cur->tlv) { - free(cur); - aim_tlvlist_free(&list); - return NULL; - } if (cur->tlv->length > 0) { - cur->tlv->value = aimbs_getraw(bs, length); + cur->tlv->value = byte_stream_getraw(bs, length); if (!cur->tlv->value) { freetlv(&cur->tlv); free(cur); @@ -137,49 +126,37 @@ * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain - * bstream references, so that at least the ->value portion of each + * bstream references, so that at least the ->value portion of each * element doesn't need to be malloc/memcpy'd. This could prove to be * just as efficient as the in-place TLV parsing used in a couple places * in libfaim. * * @param bs Input bstream - * @param num The max number of TLVs that will be read, or -1 if unlimited. - * There are a number of places where you want to read in a tlvchain, - * but the chain is not at the end of the SNAC, and the chain is + * @param num The max number of TLVs that will be read, or -1 if unlimited. + * There are a number of places where you want to read in a tlvchain, + * but the chain is not at the end of the SNAC, and the chain is * preceded by the number of TLVs. So you can limit that with this. * @return Return the TLV chain read */ -faim_internal aim_tlvlist_t *aim_tlvlist_readnum(ByteStream *bs, guint16 num) +aim_tlvlist_t *aim_tlvlist_readnum(ByteStream *bs, guint16 num) { aim_tlvlist_t *list = NULL, *cur; - while ((aim_bstream_empty(bs) > 0) && (num != 0)) { + while ((byte_stream_empty(bs) > 0) && (num != 0)) { guint16 type, length; - type = aimbs_get16(bs); - length = aimbs_get16(bs); + type = byte_stream_get16(bs); + length = byte_stream_get16(bs); - if (length > aim_bstream_empty(bs)) { + if (length > byte_stream_empty(bs)) { aim_tlvlist_free(&list); return NULL; } - cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t)); - if (!cur) { - aim_tlvlist_free(&list); - return NULL; - } - - memset(cur, 0, sizeof(aim_tlvlist_t)); - + cur = g_new0(aim_tlvlist_t, 1); cur->tlv = createtlv(type, length, NULL); - if (!cur->tlv) { - free(cur); - aim_tlvlist_free(&list); - return NULL; - } if (cur->tlv->length > 0) { - cur->tlv->value = aimbs_getraw(bs, length); + cur->tlv->value = byte_stream_getraw(bs, length); if (!cur->tlv->value) { freetlv(&cur->tlv); free(cur); @@ -206,49 +183,37 @@ * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain - * bstream references, so that at least the ->value portion of each + * bstream references, so that at least the ->value portion of each * element doesn't need to be malloc/memcpy'd. This could prove to be * just as efficient as the in-place TLV parsing used in a couple places * in libfaim. * * @param bs Input bstream * @param len The max length in bytes that will be read. - * There are a number of places where you want to read in a tlvchain, - * but the chain is not at the end of the SNAC, and the chain is + * There are a number of places where you want to read in a tlvchain, + * but the chain is not at the end of the SNAC, and the chain is * preceded by the length of the TLVs. So you can limit that with this. * @return Return the TLV chain read */ -faim_internal aim_tlvlist_t *aim_tlvlist_readlen(ByteStream *bs, guint16 len) +aim_tlvlist_t *aim_tlvlist_readlen(ByteStream *bs, guint16 len) { aim_tlvlist_t *list = NULL, *cur; - while ((aim_bstream_empty(bs) > 0) && (len > 0)) { + while ((byte_stream_empty(bs) > 0) && (len > 0)) { guint16 type, length; - type = aimbs_get16(bs); - length = aimbs_get16(bs); + type = byte_stream_get16(bs); + length = byte_stream_get16(bs); - if (length > aim_bstream_empty(bs)) { + if (length > byte_stream_empty(bs)) { aim_tlvlist_free(&list); return NULL; } - cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t)); - if (!cur) { - aim_tlvlist_free(&list); - return NULL; - } - - memset(cur, 0, sizeof(aim_tlvlist_t)); - + cur = g_new0(aim_tlvlist_t, 1); cur->tlv = createtlv(type, length, NULL); - if (!cur->tlv) { - free(cur); - aim_tlvlist_free(&list); - return NULL; - } if (cur->tlv->length > 0) { - cur->tlv->value = aimbs_getraw(bs, length); + cur->tlv->value = byte_stream_getraw(bs, length); if (!cur->tlv->value) { freetlv(&cur->tlv); free(cur); @@ -272,7 +237,7 @@ * @param orig The TLV chain you want to make a copy of. * @return A newly allocated TLV chain. */ -faim_internal aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig) +aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig) { aim_tlvlist_t *new = NULL; @@ -285,22 +250,22 @@ } /* - * Compare two TLV lists for equality. This probably is not the most + * Compare two TLV lists for equality. This probably is not the most * efficient way to do this. * * @param one One of the TLV chains to compare. * @param two The other TLV chain to compare. * @return Return 0 if the lists are the same, return 1 if they are different. */ -faim_internal int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two) +int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two) { ByteStream bs1, bs2; if (aim_tlvlist_size(&one) != aim_tlvlist_size(&two)) return 1; - aim_bstream_init(&bs1, ((guint8 *)malloc(aim_tlvlist_size(&one)*sizeof(guint8))), aim_tlvlist_size(&one)); - aim_bstream_init(&bs2, ((guint8 *)malloc(aim_tlvlist_size(&two)*sizeof(guint8))), aim_tlvlist_size(&two)); + byte_stream_init(&bs1, ((guint8 *)malloc(aim_tlvlist_size(&one)*sizeof(guint8))), aim_tlvlist_size(&one)); + byte_stream_init(&bs2, ((guint8 *)malloc(aim_tlvlist_size(&two)*sizeof(guint8))), aim_tlvlist_size(&two)); aim_tlvlist_write(&bs1, &one); aim_tlvlist_write(&bs2, &two); @@ -326,7 +291,7 @@ * * @param list Chain to be freed */ -faim_internal void aim_tlvlist_free(aim_tlvlist_t **list) +void aim_tlvlist_free(aim_tlvlist_t **list) { aim_tlvlist_t *cur; @@ -354,7 +319,7 @@ * @param list Chain to be counted. * @return The number of TLVs stored in the passed chain. */ -faim_internal int aim_tlvlist_count(aim_tlvlist_t **list) +int aim_tlvlist_count(aim_tlvlist_t **list) { aim_tlvlist_t *cur; int count; @@ -372,10 +337,10 @@ * Count the number of bytes in a TLV chain. * * @param list Chain to be sized - * @return The number of bytes that would be needed to + * @return The number of bytes that would be needed to * write the passed TLV chain to a data buffer. */ -faim_internal int aim_tlvlist_size(aim_tlvlist_t **list) +int aim_tlvlist_size(aim_tlvlist_t **list) { aim_tlvlist_t *cur; int size; @@ -399,25 +364,17 @@ * @param value String to add. * @return The size of the value added. */ -faim_internal int aim_tlvlist_add_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value) +int aim_tlvlist_add_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value) { aim_tlvlist_t *newtlv, *cur; if (list == NULL) return 0; - if (!(newtlv = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t)))) - return 0; - memset(newtlv, 0x00, sizeof(aim_tlvlist_t)); - - if (!(newtlv->tlv = createtlv(type, length, NULL))) { - free(newtlv); - return 0; - } - if (newtlv->tlv->length > 0) { - newtlv->tlv->value = (guint8 *)malloc(newtlv->tlv->length); - memcpy(newtlv->tlv->value, value, newtlv->tlv->length); - } + newtlv = g_new0(aim_tlvlist_t, 1); + newtlv->tlv = createtlv(type, length, NULL); + if (newtlv->tlv->length > 0) + newtlv->tlv->value = g_memdup(value, length); if (!*list) *list = newtlv; @@ -438,7 +395,7 @@ * @param value Value to add. * @return The size of the value added. */ -faim_internal int aim_tlvlist_add_8(aim_tlvlist_t **list, const guint16 type, const guint8 value) +int aim_tlvlist_add_8(aim_tlvlist_t **list, const guint16 type, const guint8 value) { guint8 v8[1]; @@ -455,7 +412,7 @@ * @param value Value to add. * @return The size of the value added. */ -faim_internal int aim_tlvlist_add_16(aim_tlvlist_t **list, const guint16 type, const guint16 value) +int aim_tlvlist_add_16(aim_tlvlist_t **list, const guint16 type, const guint16 value) { guint8 v16[2]; @@ -472,7 +429,7 @@ * @param value Value to add. * @return The size of the value added. */ -faim_internal int aim_tlvlist_add_32(aim_tlvlist_t **list, const guint16 type, const guint32 value) +int aim_tlvlist_add_32(aim_tlvlist_t **list, const guint16 type, const guint32 value) { guint8 v32[4]; @@ -489,7 +446,7 @@ * @param value Value to add. * @return The size of the value added. */ -faim_internal int aim_tlvlist_add_str(aim_tlvlist_t **list, const guint16 type, const char *value) +int aim_tlvlist_add_str(aim_tlvlist_t **list, const guint16 type, const char *value) { return aim_tlvlist_add_raw(list, type, strlen(value), (guint8 *)value); } @@ -498,19 +455,19 @@ * Adds a block of capability blocks to a TLV chain. The bitfield * passed in should be a bitwise %OR of any of the %AIM_CAPS constants: * - * %AIM_CAPS_BUDDYICON Supports Buddy Icons - * %AIM_CAPS_TALK Supports Voice Chat - * %AIM_CAPS_IMIMAGE Supports DirectIM/IMImage - * %AIM_CAPS_CHAT Supports Chat - * %AIM_CAPS_GETFILE Supports Get File functions - * %AIM_CAPS_SENDFILE Supports Send File functions + * %OSCAR_CAPABILITY_BUDDYICON Supports Buddy Icons + * %OSCAR_CAPABILITY_TALK Supports Voice Chat + * %OSCAR_CAPABILITY_IMIMAGE Supports DirectIM/IMImage + * %OSCAR_CAPABILITY_CHAT Supports Chat + * %OSCAR_CAPABILITY_GETFILE Supports Get File functions + * %OSCAR_CAPABILITY_SENDFILE Supports Send File functions * * @param list Destination chain * @param type TLV type to add * @param caps Bitfield of capability flags to send * @return The size of the value added. */ -faim_internal int aim_tlvlist_add_caps(aim_tlvlist_t **list, const guint16 type, const guint32 caps) +int aim_tlvlist_add_caps(aim_tlvlist_t **list, const guint16 type, const guint32 caps) { guint8 buf[16*16]; /* XXX icky fixed length buffer */ ByteStream bs; @@ -518,11 +475,11 @@ if (!caps) return 0; /* nothing there anyway */ - aim_bstream_init(&bs, buf, sizeof(buf)); + byte_stream_init(&bs, buf, sizeof(buf)); - aimbs_putcaps(&bs, caps); + byte_stream_putcaps(&bs, caps); - return aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf); + return aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), buf); } /** @@ -532,16 +489,16 @@ * @param type TLV type to add. * @return The size of the value added. */ -faim_internal int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *userinfo) +int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *userinfo) { guint8 buf[1024]; /* bleh */ ByteStream bs; - aim_bstream_init(&bs, buf, sizeof(buf)); + byte_stream_init(&bs, buf, sizeof(buf)); aim_putuserinfo(&bs, userinfo); - return aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf); + return aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), buf); } /** @@ -553,7 +510,7 @@ * @param instance The instance. * @return The size of the value added. */ -faim_internal int aim_tlvlist_add_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance) +int aim_tlvlist_add_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance) { guint8 *buf; int len; @@ -561,17 +518,15 @@ len = 2 + 1 + strlen(roomname) + 2; - if (!(buf = malloc(len))) - return 0; - - aim_bstream_init(&bs, buf, len); + buf = malloc(len); + byte_stream_init(&bs, buf, len); - aimbs_put16(&bs, exchange); - aimbs_put8(&bs, strlen(roomname)); - aimbs_putstr(&bs, roomname); - aimbs_put16(&bs, instance); + byte_stream_put16(&bs, exchange); + byte_stream_put8(&bs, strlen(roomname)); + byte_stream_putstr(&bs, roomname); + byte_stream_put16(&bs, instance); - len = aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf); + len = aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), buf); free(buf); @@ -585,7 +540,7 @@ * @param type TLV type to add. * @return The size of the value added. */ -faim_internal int aim_tlvlist_add_noval(aim_tlvlist_t **list, const guint16 type) +int aim_tlvlist_add_noval(aim_tlvlist_t **list, const guint16 type) { return aim_tlvlist_add_raw(list, type, 0, NULL); } @@ -596,7 +551,7 @@ * made to this. * * XXX should probably support sublists for real. - * + * * This is so neat. * * @param list Destination chain. @@ -606,7 +561,7 @@ * 0 is returned if there was an error or if the destination * TLV chain has length 0. */ -faim_internal int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl) +int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl) { guint8 *buf; int buflen; @@ -617,14 +572,13 @@ if (buflen <= 0) return 0; - if (!(buf = malloc(buflen))) - return 0; + buf = malloc(buflen); - aim_bstream_init(&bs, buf, buflen); + byte_stream_init(&bs, buf, buflen); aim_tlvlist_write(&bs, tl); - aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf); + aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), buf); free(buf); @@ -632,8 +586,8 @@ } /** - * Substitute a TLV of a given type with a new TLV of the same type. If - * you attempt to replace a TLV that does not exist, this function will + * Substitute a TLV of a given type with a new TLV of the same type. If + * you attempt to replace a TLV that does not exist, this function will * just add a new TLV as if you called aim_tlvlist_add_raw(). * * @param list Desination chain (%NULL pointer if empty). @@ -642,7 +596,7 @@ * @param value String to add. * @return The length of the TLV. */ -faim_internal int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value) +int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value) { aim_tlvlist_t *cur; @@ -656,8 +610,7 @@ free(cur->tlv->value); cur->tlv->length = length; if (cur->tlv->length > 0) { - cur->tlv->value = (guint8 *)malloc(cur->tlv->length); - memcpy(cur->tlv->value, value, cur->tlv->length); + cur->tlv->value = g_memdup(value, length); } else cur->tlv->value = NULL; @@ -674,7 +627,7 @@ * @param str String to add. * @return The length of the TLV. */ -faim_internal int aim_tlvlist_replace_str(aim_tlvlist_t **list, const guint16 type, const char *str) +int aim_tlvlist_replace_str(aim_tlvlist_t **list, const guint16 type, const char *str) { return aim_tlvlist_replace_raw(list, type, strlen(str), (const guchar *)str); } @@ -688,7 +641,7 @@ * @param type TLV type. * @return The length of the TLV. */ -faim_internal int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const guint16 type) +int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const guint16 type) { return aim_tlvlist_replace_raw(list, type, 0, NULL); } @@ -703,7 +656,7 @@ * @param value 8 bit value to add. * @return The length of the TLV. */ -faim_internal int aim_tlvlist_replace_8(aim_tlvlist_t **list, const guint16 type, const guint8 value) +int aim_tlvlist_replace_8(aim_tlvlist_t **list, const guint16 type, const guint8 value) { guint8 v8[1]; @@ -713,8 +666,8 @@ } /** - * Substitute a TLV of a given type with a new TLV of the same type. If - * you attempt to replace a TLV that does not exist, this function will + * Substitute a TLV of a given type with a new TLV of the same type. If + * you attempt to replace a TLV that does not exist, this function will * just add a new TLV as if you called aim_tlvlist_add_raw(). * * @param list Desination chain (%NULL pointer if empty). @@ -722,7 +675,7 @@ * @param value 32 bit value to add. * @return The length of the TLV. */ -faim_internal int aim_tlvlist_replace_32(aim_tlvlist_t **list, const guint16 type, const guint32 value) +int aim_tlvlist_replace_32(aim_tlvlist_t **list, const guint16 type, const guint32 value) { guint8 v32[4]; @@ -732,13 +685,13 @@ } /** - * Remove a TLV of a given type. If you attempt to remove a TLV that + * Remove a TLV of a given type. If you attempt to remove a TLV that * does not exist, nothing happens. * * @param list Desination chain (%NULL pointer if empty). * @param type TLV type. */ -faim_internal void aim_tlvlist_remove(aim_tlvlist_t **list, const guint16 type) +void aim_tlvlist_remove(aim_tlvlist_t **list, const guint16 type) { aim_tlvlist_t *del; @@ -768,17 +721,17 @@ * Write a TLV chain into a data buffer. * * Copies a TLV chain into a raw data buffer, writing only the number - * of bytes specified. This operation does not free the chain; + * of bytes specified. This operation does not free the chain; * aim_tlvlist_free() must still be called to free up the memory used * by the chain structures. * - * XXX clean this up, make better use of bstreams + * XXX clean this up, make better use of bstreams * * @param bs Input bstream * @param list Source TLV chain * @return Return 0 if the destination bstream is too small. */ -faim_internal int aim_tlvlist_write(ByteStream *bs, aim_tlvlist_t **list) +int aim_tlvlist_write(ByteStream *bs, aim_tlvlist_t **list) { int goodbuflen; aim_tlvlist_t *cur; @@ -786,15 +739,15 @@ /* do an initial run to test total length */ goodbuflen = aim_tlvlist_size(list); - if (goodbuflen > aim_bstream_empty(bs)) + if (goodbuflen > byte_stream_empty(bs)) return 0; /* not enough buffer */ /* do the real write-out */ for (cur = *list; cur; cur = cur->next) { - aimbs_put16(bs, cur->tlv->type); - aimbs_put16(bs, cur->tlv->length); + byte_stream_put16(bs, cur->tlv->type); + byte_stream_put16(bs, cur->tlv->length); if (cur->tlv->length) - aimbs_putraw(bs, cur->tlv->value, cur->tlv->length); + byte_stream_putraw(bs, cur->tlv->value, cur->tlv->length); } return 1; /* XXX this is a nonsensical return */ @@ -804,7 +757,7 @@ /** * Grab the Nth TLV of type type in the TLV list list. * - * Returns a pointer to an aim_tlv_t of the specified type; + * Returns a pointer to an aim_tlv_t of the specified type; * %NULL on error. The @nth parameter is specified starting at %1. * In most cases, there will be no more than one TLV of any type * in a chain. @@ -814,7 +767,7 @@ * @param nth Index of TLV of type to get. * @return The TLV you were looking for, or NULL if one could not be found. */ -faim_internal aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, const guint16 type, const int nth) +aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, const guint16 type, const int nth) { aim_tlvlist_t *cur; int i; @@ -840,7 +793,7 @@ * @return The length of the data in this TLV, or -1 if the TLV could not be * found. Unless -1 is returned, this value will be 2 bytes. */ -faim_internal int aim_tlv_getlength(aim_tlvlist_t *list, const guint16 type, const int nth) +int aim_tlv_getlength(aim_tlvlist_t *list, const guint16 type, const int nth) { aim_tlvlist_t *cur; int i; @@ -867,32 +820,32 @@ * not be found. This is a dynamic buffer and must be freed by the * caller. */ -faim_internal char *aim_tlv_getstr(aim_tlvlist_t *list, const guint16 type, const int nth) +char *aim_tlv_getstr(aim_tlvlist_t *list, const guint16 type, const int nth) { aim_tlv_t *tlv; - char *newstr; + char *ret; if (!(tlv = aim_tlv_gettlv(list, type, nth))) return NULL; - newstr = (char *) malloc(tlv->length + 1); - memcpy(newstr, tlv->value, tlv->length); - newstr[tlv->length] = '\0'; + ret = malloc(tlv->length + 1); + memcpy(ret, tlv->value, tlv->length); + ret[tlv->length] = '\0'; - return newstr; + return ret; } /** - * Retrieve the data from the nth TLV in the given TLV chain as an 8bit + * Retrieve the data from the nth TLV in the given TLV chain as an 8bit * integer. * * @param list Source TLV chain. * @param type TLV type to search for. * @param nth Index of TLV to return. - * @return The value the TLV you were looking for, or 0 if one could + * @return The value the TLV you were looking for, or 0 if one could * not be found. */ -faim_internal guint8 aim_tlv_get8(aim_tlvlist_t *list, const guint16 type, const int nth) +guint8 aim_tlv_get8(aim_tlvlist_t *list, const guint16 type, const int nth) { aim_tlv_t *tlv; @@ -902,16 +855,16 @@ } /** - * Retrieve the data from the nth TLV in the given TLV chain as a 16bit + * Retrieve the data from the nth TLV in the given TLV chain as a 16bit * integer. * * @param list Source TLV chain. * @param type TLV type to search for. * @param nth Index of TLV to return. - * @return The value the TLV you were looking for, or 0 if one could + * @return The value the TLV you were looking for, or 0 if one could * not be found. */ -faim_internal guint16 aim_tlv_get16(aim_tlvlist_t *list, const guint16 type, const int nth) +guint16 aim_tlv_get16(aim_tlvlist_t *list, const guint16 type, const int nth) { aim_tlv_t *tlv; @@ -921,16 +874,16 @@ } /** - * Retrieve the data from the nth TLV in the given TLV chain as a 32bit + * Retrieve the data from the nth TLV in the given TLV chain as a 32bit * integer. * * @param list Source TLV chain. * @param type TLV type to search for. * @param nth Index of TLV to return. - * @return The value the TLV you were looking for, or 0 if one could + * @return The value the TLV you were looking for, or 0 if one could * not be found. */ -faim_internal guint32 aim_tlv_get32(aim_tlvlist_t *list, const guint16 type, const int nth) +guint32 aim_tlv_get32(aim_tlvlist_t *list, const guint16 type, const int nth) { aim_tlv_t *tlv;
--- a/src/protocols/oscar/txqueue.c Fri Apr 07 01:05:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,423 +0,0 @@ -/* - * 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 -*/ - -/* - * txqueue.c - * - * Herein lies all the management routines for the transmit (Tx) queue. - * - */ - -#include "oscar.h" -#include "peer.h" - -#ifndef _WIN32 -#include <sys/socket.h> -#else -#include "win32dep.h" -#endif - -/* - * Allocate a new tx frame. - * - * This is more for looks than anything else. - * - * Right now, that is. If/when we implement a pool of transmit - * frames, this will become the request-an-unused-frame part. - * - * framing = AIM_FRAMETYPE_OFT/FLAP - * chan = channel for FLAP, hdrtype for OFT - * - */ -FlapFrame * -flap_frame_new(OscarSession *sess, OscarConnection *conn, guint8 framing, guint16 chan, int datalen) -{ - FlapFrame *fr; - - if (!sess || !conn) { - gaim_debug_misc("oscar", "flap_frame_new: No session or no connection specified!\n"); - return NULL; - } - - /* For sanity... */ - if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) || (conn->type == AIM_CONN_TYPE_LISTENER)) { - if (framing != AIM_FRAMETYPE_OFT) { - gaim_debug_misc("oscar", "flap_frame_new: attempted to allocate inappropriate frame type for rendezvous connection\n"); - return NULL; - } - } else { - if (framing != AIM_FRAMETYPE_FLAP) { - gaim_debug_misc("oscar", "flap_frame_new: attempted to allocate inappropriate frame type for FLAP connection\n"); - return NULL; - } - } - - fr = g_new0(FlapFrame, 1); - fr->conn = conn; - fr->hdrtype = framing; - if (fr->hdrtype == AIM_FRAMETYPE_FLAP) - fr->hdr.flap.channel = chan; - else if (fr->hdrtype == AIM_FRAMETYPE_OFT) - fr->hdr.rend.type = chan; - else - gaim_debug_misc("oscar", "tx_new: unknown framing\n"); - - if (datalen > 0) { - guint8 *data; - data = malloc(datalen); - aim_bstream_init(&fr->data, data, datalen); - } - - return fr; -} - -static int -aim_send(int fd, const void *buf, size_t count) -{ - int left, cur; - - for (cur = 0, left = count; left; ) { - int ret; - - ret = send(fd, ((unsigned char *)buf)+cur, left, 0); - - if (ret == -1) - return -1; - else if (ret == 0) - return cur; - - cur += ret; - left -= ret; - } - - return cur; -} - -int -aim_bstream_send(ByteStream *bs, OscarConnection *conn, size_t count) -{ - int wrote = 0; - - if (!bs || !conn) - return -EINVAL; - - /* Make sure we don't send past the end of the bs */ - if (count > aim_bstream_empty(bs)) - count = aim_bstream_empty(bs); /* truncate to remaining space */ - - if (count) { - /* - * I need to rewrite this. "Updating the UI" doesn't make sense. The program is - * blocked and the UI can't redraw. We're blocking all of Gaim. We need to set - * up an actual txqueue and a GAIM_INPUT_WRITE callback and only write when we - * can. Why is this file called txqueue anyway? Lets rename it to txblock. - */ - if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) && - (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)) { - const char *sn = aim_odc_getsn(conn); - aim_rxcallback_t userfunc; - - while (count - wrote > 1024) { - int ret; - - ret = aim_send(conn->fd, bs->data + bs->offset + wrote, 1024); - if (ret > 0) - wrote += ret; - if (ret < 0) - return -1; - if ((userfunc=aim_callhandler(conn->sessv, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER))) - userfunc(conn->sessv, NULL, sn, count-wrote>1024 ? ((double)wrote / count) : 1); - } - } - - if (count - wrote) { - wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, count - wrote); - } - } - - bs->offset += wrote; - - return wrote; -} - -static int -sendframe_flap(OscarSession *sess, FlapFrame *fr) -{ - ByteStream bs; - guint8 *bs_raw; - int payloadlen, err = 0, bslen; - - payloadlen = aim_bstream_curpos(&fr->data); - - bs_raw = malloc(6 + payloadlen); - - aim_bstream_init(&bs, bs_raw, 6 + payloadlen); - - /* FLAP header */ - aimbs_put8(&bs, 0x2a); - aimbs_put8(&bs, fr->hdr.flap.channel); - aimbs_put16(&bs, fr->hdr.flap.seqnum); - aimbs_put16(&bs, payloadlen); - - /* payload */ - aim_bstream_rewind(&fr->data); - aimbs_putbs(&bs, &fr->data, payloadlen); - - bslen = aim_bstream_curpos(&bs); - aim_bstream_rewind(&bs); - if (aim_bstream_send(&bs, fr->conn, bslen) != bslen) - err = -errno; - - free(bs_raw); /* XXX aim_bstream_free */ - - fr->handled = 1; - fr->conn->lastactivity = time(NULL); - - return err; -} - -static int -sendframe_rendezvous(OscarSession *sess, FlapFrame *fr) -{ - ByteStream bs; - guint8 *bs_raw; - int payloadlen, err = 0, bslen; - - payloadlen = aim_bstream_curpos(&fr->data); - - bs_raw = malloc(8 + payloadlen); - - aim_bstream_init(&bs, bs_raw, 8 + payloadlen); - - /* Rendezvous header */ - aimbs_putraw(&bs, fr->hdr.rend.magic, 4); - aimbs_put16(&bs, fr->hdr.rend.hdrlen); - aimbs_put16(&bs, fr->hdr.rend.type); - - /* payload */ - aim_bstream_rewind(&fr->data); - aimbs_putbs(&bs, &fr->data, payloadlen); - - bslen = aim_bstream_curpos(&bs); - aim_bstream_rewind(&bs); - if (aim_bstream_send(&bs, fr->conn, bslen) != bslen) - err = -errno; - - free(bs_raw); /* XXX aim_bstream_free */ - - fr->handled = 1; - fr->conn->lastactivity = time(NULL); - - return err; -} - -static int -aim_tx_sendframe(OscarSession *sess, FlapFrame *fr) -{ - if (fr->hdrtype == AIM_FRAMETYPE_FLAP) - return sendframe_flap(sess, fr); - else if (fr->hdrtype == AIM_FRAMETYPE_OFT) - return sendframe_rendezvous(sess, fr); - - return -1; -} - -/* - * This is responsible for removing sent commands from the transmit - * queue. This is not a required operation, but it of course helps - * reduce memory footprint at run time! - */ -static void -aim_tx_purgequeue(OscarSession *sess) -{ - FlapFrame *cur, **prev; - - for (prev = &sess->queue_outgoing; (cur = *prev); ) { - if (cur->handled) { - *prev = cur->next; - aim_frame_destroy(cur); - } else - prev = &cur->next; - } - - return; -} - -int -aim_tx_flushqueue(OscarSession *sess) -{ - FlapFrame *cur; - - for (cur = sess->queue_outgoing; cur; cur = cur->next) { - - if (cur->handled) - continue; /* already been sent */ - - if (cur->conn && (cur->conn->status & AIM_CONN_STATUS_INPROGRESS)) - continue; - - /* XXX this should call the custom "queuing" function!! */ - aim_tx_sendframe(sess, cur); - } - - /* purge sent commands from queue */ - aim_tx_purgequeue(sess); - - return 0; -} - -/** - * Get rid of packets waiting for tx on a dying conn. For now this - * simply marks all packets as sent and lets them disappear without - * warning. - * - * @param sess A session. - * @param conn Connection that's dying. - */ -void -aim_tx_cleanqueue(OscarSession *sess, OscarConnection *conn) -{ - FlapFrame *cur; - - for (cur = sess->queue_outgoing; cur; cur = cur->next) { - if (cur->conn == conn) - cur->handled = 1; - } - - return; -} - -/* - * This increments the tx command count, and returns the seqnum - * that should be stamped on the next FLAP packet sent. This is - * normally called during the final step of packet preparation - * before enqueuement (in aim_tx_enqueue()). - */ -static flap_seqnum_t -aim_get_next_txseqnum(OscarConnection *conn) -{ - flap_seqnum_t ret; - - ret = ++conn->seqnum; - - return ret; -} - -/* - * The overall purpose here is to enqueue the passed in command struct - * into the outgoing (tx) queue. Basically... - * 1) Make a scope-irrelevant copy of the struct - * 3) Mark as not-sent-yet - * 4) Enqueue the struct into the list - * 6) Return - * - * Note that this is only used when doing queue-based transmitting; - * that is, when sess->tx_enqueue is set to &aim_tx_enqueue__queuebased. - * - */ -static int -aim_tx_enqueue__queuebased(OscarSession *sess, FlapFrame *fr) -{ - - if (!fr->conn) { - gaim_debug_warning("oscar", "aim_tx_enqueue: enqueueing packet with no connecetion\n"); - fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS); - } - - if (fr->hdrtype == AIM_FRAMETYPE_FLAP) { - /* assign seqnum -- XXX should really not assign until hardxmit */ - fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn); - } - - fr->handled = 0; /* not sent yet */ - - /* see overhead note in aim_rxqueue counterpart */ - if (!sess->queue_outgoing) - sess->queue_outgoing = fr; - else { - FlapFrame *cur; - for (cur = sess->queue_outgoing; cur->next; cur = cur->next); - cur->next = fr; - } - - return 0; -} - -/* - * Parallel to aim_tx_enqueue__queuebased, however, this bypasses - * the whole queue mess when you want immediate writes to happen. - * - * Basically the same as its __queuebased couterpart, however - * instead of doing a list append, it just calls aim_tx_sendframe() - * right here. - * - */ -static int -aim_tx_enqueue__immediate(OscarSession *sess, FlapFrame *fr) -{ - int ret; - - if (!fr->conn) { - gaim_debug_error("oscar", "aim_tx_enqueue: packet has no connection\n"); - aim_frame_destroy(fr); - return 0; - } - - if (fr->hdrtype == AIM_FRAMETYPE_FLAP) - fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn); - - fr->handled = 0; /* not sent yet */ - - ret = aim_tx_sendframe(sess, fr); - - aim_frame_destroy(fr); - - return ret; -} - -int -aim_tx_setenqueue(OscarSession *sess, int what, int (*func)(OscarSession *, FlapFrame *)) -{ - - if (what == AIM_TX_QUEUED) - sess->tx_enqueue = &aim_tx_enqueue__queuebased; - else if (what == AIM_TX_IMMEDIATE) - sess->tx_enqueue = &aim_tx_enqueue__immediate; - else - return -EINVAL; /* unknown action */ - - return 0; -} - -int -aim_tx_enqueue(OscarSession *sess, FlapFrame *fr) -{ - /* - * If we want to send on a connection that is in progress, we have to force - * them to use the queue based version. Otherwise, use whatever they - * want. - */ - if (fr && fr->conn && - (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) { - return aim_tx_enqueue__queuebased(sess, fr); - } - - return (*sess->tx_enqueue)(sess, fr); -}
--- a/src/protocols/oscar/util.c Fri Apr 07 01:05:48 2006 +0000 +++ b/src/protocols/oscar/util.c Fri Apr 07 05:10:56 2006 +0000 @@ -37,7 +37,7 @@ * -- DMP. * */ -faim_export int aimutil_tokslen(char *toSearch, int theindex, char dl) +int aimutil_tokslen(char *toSearch, int theindex, char dl) { int curCount = 1; char *next; @@ -61,7 +61,7 @@ return toReturn; } -faim_export int aimutil_itemcnt(char *toSearch, char dl) +int aimutil_itemcnt(char *toSearch, char dl) { int curCount; char *next; @@ -78,7 +78,7 @@ return curCount; } -faim_export char *aimutil_itemindex(char *toSearch, int theindex, char dl) +char *aimutil_itemindex(char *toSearch, int theindex, char dl) { int curCount; char *next; @@ -122,7 +122,7 @@ * Calculate the checksum of a given icon. * */ -faim_export guint16 aimutil_iconsum(const guint8 *buf, int buflen) +guint16 aimutil_iconsum(const guint8 *buf, int buflen) { guint32 sum; int i; @@ -201,7 +201,7 @@ * * @return 1 if the screen name is valid, 0 if not. */ -faim_export int aim_snvalid(const char *sn) +int aim_snvalid(const char *sn) { if ((sn == NULL) || (*sn == '\0')) return 0; @@ -224,7 +224,7 @@ * @return 1 if the screen name is an ICQ screen name. Otherwise 0 * is returned. */ -faim_export int aim_sn_is_icq(const char *sn) +int aim_sn_is_icq(const char *sn) { if (isalpha(sn[0])) return 0; @@ -239,7 +239,7 @@ * @return 1 if the screen name is an SMS number. Otherwise 0 * is returned. */ -faim_export int aim_sn_is_sms(const char *sn) +int aim_sn_is_sms(const char *sn) { if (sn[0] != '+') return 0; @@ -254,7 +254,7 @@ * return is equal to that of strlen(). * */ -faim_export int aim_snlen(const char *sn) +int aim_snlen(const char *sn) { int i = 0; @@ -283,7 +283,7 @@ * non-0 if different * */ -faim_export int aim_sncmp(const char *sn1, const char *sn2) +int aim_sncmp(const char *sn1, const char *sn2) { if ((sn1 == NULL) || (sn2 == NULL))