Mercurial > pidgin
comparison src/protocols/oscar/im.c @ 3952:07283934dedd
[gaim-migrate @ 4133]
Ok, big commit with little functionality change.
Most of it is me shuffling crap around because I'm one of them neat freaks. Lots of general code
cleanup too. I'm trying to move to that whole "one-family-per-file" thing.
The details...
I added libfaim support for aim's new search family, 0x000f. I only tested this briefly, so if
anyone uses it for anything, be aware that it could be buggy. I'll add oscar support sometime.
Advantages of this family are... when you search for someone, you get the directory info for that
person. So like, first name, middle name, last name, maiden name, city, state, country, zip,
address, interests, nickname, and maybe some other stuff. Basically all the info that they've set in
their directory info thing. Info. Oh, and I'm calling it "new search" because seach was already
taken, and cookie monster ate my right brain.
The reason I didn't add support to oscar.c... the new search family requires making a connection to
another server. While moving stuff around I realized that I didn't really like how new connections
are made. It's kind of sloppy. I'm thinking it would be nice to have an outgoing queue for each
type of connection, and then let the client queue messages as much as they want. Then, if libfaim
sees that there is a message for a certain type of connection, and there is no open connection of
that type, it will connect, and then flush the queue when the connection is made. This seems a lot
cleaner, but it also seems like a pain in the ass. I should do ssi for icq first, anyway :-)
Also, I think it would be neat if there was an ICBM file that handled channels 1 through 4. Then
im.c and chat.c could pass the ICBM part to the icbm stuff and it could get parsed there. im.c is
really huge right now.
I applied a patch from Graham Booker that paves the way for unicode in direct IMs. Thanks Graham.
Now we just need Paco-Paco to git a little free time and write a patch for this.
http://sourceforge.net/tracker/index.php?func=detail&aid=633589&group_id=235&atid=300235
I applied 2 patches from Will Mahan dealing with file transfer/oft/rendezous/whatever. Here's some
info on them, from The Man himself:
Patch 1
"Currently the Rendezvous code is rather messy; this
patch attempts to bring it up to speed with the rest of
the Oscar prpl. Its changes include:
* Rewrite several ft.c functions to use bstreams.
Apparently the code in question was written before
bstreams were implemented.
* Handle incoming Rendezvous packets through the
rxqueue like FLAP packets, rather than handling them as
a special case as soon as they are received. This
takes advantage of the bstream cleanup to unify some
code and simplify the aim_frame_t struct.
* Change some names used to try to clarify the
distinction between OFT, which refers specifically to
file transfer, and Rendezvous, which encompasses OFT as
well as other types of client-to-client connections."
Patch 2
"* Add some comments I inadvertently left out of my last patch.
* Fix a double-free that occurs when connections time out.
* Correct a bug causing filenames to be truncated by 4 characters on
some clients.
* Preserve directory structure when sending multiple files.
* Handle (throw away) resource forks sent by Mac clients."
I also changed all indents to tabs in ft.c.
And split all the bstream stuff from rxqueue.c and put it in bstream.c. It really is a separate
thing. Especially since it can be used for outgoing connections.
Also, I was going to look over the whole patch tonight to make sure it's all good, but it's like 6000
lines, so, uh, I'll do it later.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Wed, 13 Nov 2002 07:01:37 +0000 |
parents | 765769211688 |
children | 2532f1192da3 |
comparison
equal
deleted
inserted
replaced
3951:32942c49dced | 3952:07283934dedd |
---|---|
6 * the ICBM types (family 4), a channel is defined. Each channel | 6 * the ICBM types (family 4), a channel is defined. Each channel |
7 * represents a different type of message. Channel 1 is used for | 7 * represents a different type of message. Channel 1 is used for |
8 * what would commonly be called an "instant message". Channel 2 | 8 * what would commonly be called an "instant message". Channel 2 |
9 * is used for negotiating "rendezvous". These transactions end in | 9 * is used for negotiating "rendezvous". These transactions end in |
10 * something more complex happening, such as a chat invitation, or | 10 * something more complex happening, such as a chat invitation, or |
11 * a file transfer. Channel 4 is used for various ICQ messages. | 11 * a file transfer. Channel 3 is used for chat messages (not in |
12 * Examples are normal messages, URLs, and old-style authorization. | 12 * the same family as these channels). Channel 4 is used for |
13 * various ICQ messages. Examples are normal messages, URLs, and | |
14 * old-style authorization. | |
13 * | 15 * |
14 * In addition to the channel, every ICBM contains a cookie. For | 16 * In addition to the channel, every ICBM contains a cookie. For |
15 * standard IMs, these are only used for error messages. However, | 17 * standard IMs, these are only used for error messages. However, |
16 * the more complex rendezvous messages make suitably more complex | 18 * the more complex rendezvous messages make suitably more complex |
17 * use of this field. | 19 * use of this field. |
86 } | 88 } |
87 | 89 |
88 return AIM_CLIENTTYPE_UNKNOWN; | 90 return AIM_CLIENTTYPE_UNKNOWN; |
89 } | 91 } |
90 | 92 |
93 /* | |
94 * Subtype 0x0002 | |
95 * | |
96 * I definitly recommend sending this. If you don't, you'll be stuck | |
97 * with the rather unreasonable defaults. You don't want those. Send this. | |
98 * | |
99 */ | |
100 faim_export int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params) | |
101 { | |
102 aim_conn_t *conn; | |
103 aim_frame_t *fr; | |
104 aim_snacid_t snacid; | |
105 | |
106 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) | |
107 return -EINVAL; | |
108 | |
109 if (!params) | |
110 return -EINVAL; | |
111 | |
112 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+16))) | |
113 return -ENOMEM; | |
114 | |
115 snacid = aim_cachesnac(sess, 0x0004, 0x0002, 0x0000, NULL, 0); | |
116 aim_putsnac(&fr->data, 0x0004, 0x0002, 0x0000, snacid); | |
117 | |
118 /* This is read-only (see Parameter Reply). Must be set to zero here. */ | |
119 aimbs_put16(&fr->data, 0x0000); | |
120 | |
121 /* These are all read-write */ | |
122 aimbs_put32(&fr->data, params->flags); | |
123 aimbs_put16(&fr->data, params->maxmsglen); | |
124 aimbs_put16(&fr->data, params->maxsenderwarn); | |
125 aimbs_put16(&fr->data, params->maxrecverwarn); | |
126 aimbs_put32(&fr->data, params->minmsginterval); | |
127 | |
128 aim_tx_enqueue(sess, fr); | |
129 | |
130 return 0; | |
131 } | |
132 | |
133 /* Subtype 0x0004 - Request ICBM parameter information. */ | |
134 faim_export int aim_reqicbmparams(aim_session_t *sess) | |
135 { | |
136 aim_conn_t *conn; | |
137 | |
138 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) | |
139 return -EINVAL; | |
140 | |
141 return aim_genericreq_n(sess, conn, 0x0004, 0x0004); | |
142 } | |
143 | |
144 /* Subtype 0x0005 */ | |
145 static int paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) | |
146 { | |
147 struct aim_icbmparameters params; | |
148 aim_rxcallback_t userfunc; | |
149 | |
150 params.maxchan = aimbs_get16(bs); | |
151 params.flags = aimbs_get32(bs); | |
152 params.maxmsglen = aimbs_get16(bs); | |
153 params.maxsenderwarn = aimbs_get16(bs); | |
154 params.maxrecverwarn = aimbs_get16(bs); | |
155 params.minmsginterval = aimbs_get32(bs); | |
156 | |
157 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | |
158 return userfunc(sess, rx, ¶ms); | |
159 | |
160 return 0; | |
161 } | |
162 | |
91 /* This should be endian-safe now... but who knows... */ | 163 /* This should be endian-safe now... but who knows... */ |
92 faim_export fu16_t aim_iconsum(const fu8_t *buf, int buflen) | 164 faim_export fu16_t aim_iconsum(const fu8_t *buf, int buflen) |
93 { | 165 { |
94 fu32_t sum; | 166 fu32_t sum; |
95 int i; | 167 int i; |
103 | 175 |
104 return (fu16_t)sum; | 176 return (fu16_t)sum; |
105 } | 177 } |
106 | 178 |
107 /* | 179 /* |
108 * Send an ICBM (instant message). | 180 * Subtype 0x0006 - Send an ICBM (instant message). |
109 * | 181 * |
110 * | 182 * |
111 * Possible flags: | 183 * Possible flags: |
112 * AIM_IMFLAGS_AWAY -- Marks the message as an autoresponse | 184 * AIM_IMFLAGS_AWAY -- Marks the message as an autoresponse |
113 * AIM_IMFLAGS_ACK -- Requests that the server send an ack | 185 * AIM_IMFLAGS_ACK -- Requests that the server send an ack |
371 | 443 |
372 return aim_send_im_ext(sess, &args); | 444 return aim_send_im_ext(sess, &args); |
373 } | 445 } |
374 | 446 |
375 /* | 447 /* |
448 * Subtype 0x0006 | |
449 * | |
376 * This is also performance sensitive. (If you can believe it...) | 450 * This is also performance sensitive. (If you can believe it...) |
377 * | 451 * |
378 */ | 452 */ |
379 faim_export int aim_send_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum) | 453 faim_export int aim_send_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum) |
380 { | 454 { |
454 | 528 |
455 return 0; | 529 return 0; |
456 } | 530 } |
457 | 531 |
458 /* | 532 /* |
533 * Subtype 0x0006 | |
534 * | |
459 * This only works for ICQ 2001b (thats 2001 not 2000). Better, only | 535 * This only works for ICQ 2001b (thats 2001 not 2000). Better, only |
460 * send it to clients advertising the RTF capability. In fact, if you send | 536 * send it to clients advertising the RTF capability. In fact, if you send |
461 * it to a client that doesn't support that capability, the server will gladly | 537 * it to a client that doesn't support that capability, the server will gladly |
462 * bounce it back to you. | 538 * bounce it back to you. |
463 * | 539 * |
569 aim_tx_enqueue(sess, fr); | 645 aim_tx_enqueue(sess, fr); |
570 | 646 |
571 return 0; | 647 return 0; |
572 } | 648 } |
573 | 649 |
650 /* Subtype 0x0006 */ | |
574 faim_internal int aim_request_directim(aim_session_t *sess, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret) | 651 faim_internal int aim_request_directim(aim_session_t *sess, const char *destsn, fu8_t *ip, fu16_t port, fu8_t *ckret) |
575 { | 652 { |
576 aim_conn_t *conn; | 653 aim_conn_t *conn; |
577 fu8_t ck[8]; | 654 fu8_t ck[8]; |
578 aim_frame_t *fr; | 655 aim_frame_t *fr; |
645 aim_tx_enqueue(sess, fr); | 722 aim_tx_enqueue(sess, fr); |
646 | 723 |
647 return 0; | 724 return 0; |
648 } | 725 } |
649 | 726 |
727 /* Subtype 0x0006 */ | |
650 faim_internal int aim_request_sendfile(aim_session_t *sess, const char *sn, const char *filename, fu16_t numfiles, fu32_t totsize, fu8_t *ip, fu16_t port, fu8_t *ckret) | 728 faim_internal int aim_request_sendfile(aim_session_t *sess, const char *sn, const char *filename, fu16_t numfiles, fu32_t totsize, fu8_t *ip, fu16_t port, fu8_t *ckret) |
651 { | 729 { |
652 aim_conn_t *conn; | 730 aim_conn_t *conn; |
653 int i; | 731 int i; |
654 fu8_t ck[8]; | 732 fu8_t ck[8]; |
751 | 829 |
752 return 0; | 830 return 0; |
753 } | 831 } |
754 | 832 |
755 /** | 833 /** |
756 * Request the status message of the given ICQ user. | 834 * Subtype 0x0006 - Request the status message of the given ICQ user. |
757 * | 835 * |
758 * @param sess The oscar session. | 836 * @param sess The oscar session. |
759 * @param sn The UIN of the user of whom you wish to request info. | 837 * @param sn The UIN of the user of whom you wish to request info. |
760 * @param type The type of info you wish to request. This should be the current | 838 * @param type The type of info you wish to request. This should be the current |
761 * state of the user, as one of the AIM_ICQ_STATE_* defines. | 839 * state of the user, as one of the AIM_ICQ_STATE_* defines. |
815 /* TLV t(2711) */ | 893 /* TLV t(2711) */ |
816 aimbs_put16(&fr->data, 0x2711); | 894 aimbs_put16(&fr->data, 0x2711); |
817 aimbs_put16(&fr->data, 0x0036); | 895 aimbs_put16(&fr->data, 0x0036); |
818 { /* V */ | 896 { /* V */ |
819 aimbs_putle16(&fr->data, 0x001b); /* L */ | 897 aimbs_putle16(&fr->data, 0x001b); /* L */ |
820 aimbs_putle16(&fr->data, 0x0008); /* AAA - Protocol version */ | 898 aimbs_putle16(&fr->data, 0x0008); /* XXX - Protocol version */ |
821 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ | 899 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ |
822 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ | 900 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ |
823 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ | 901 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ |
824 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ | 902 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ |
825 aimbs_putle16(&fr->data, 0x0000); /* Unknown */ | 903 aimbs_putle16(&fr->data, 0x0000); /* Unknown */ |
861 | 939 |
862 return 0; | 940 return 0; |
863 } | 941 } |
864 | 942 |
865 /** | 943 /** |
944 * Subtype 0x0006 | |
945 * | |
866 * This can be used to send an ICQ authorization reply (deny or grant). It is the "old way." | 946 * This can be used to send an ICQ authorization reply (deny or grant). It is the "old way." |
867 * The new way is to use SSI. I like the new way a lot better. This seems like such a hack, | 947 * The new way is to use SSI. I like the new way a lot better. This seems like such a hack, |
868 * mostly because it's in network byte order. Figuring this stuff out sometimes takes a while, | 948 * mostly because it's in network byte order. Figuring this stuff out sometimes takes a while, |
869 * but thats ok, because it gives me time to try to figure out what kind of drugs the AOL people | 949 * but thats ok, because it gives me time to try to figure out what kind of drugs the AOL people |
870 * were taking when they merged the two protocols. | 950 * were taking when they merged the two protocols. |
1552 { | 1632 { |
1553 | 1633 |
1554 args->destructor = (void *)incomingim_ch2_sendfile_free; | 1634 args->destructor = (void *)incomingim_ch2_sendfile_free; |
1555 | 1635 |
1556 if (servdata) { | 1636 if (servdata) { |
1637 int flen; | |
1638 | |
1557 /* subtype is one of AIM_OFT_SUBTYPE_* */ | 1639 /* subtype is one of AIM_OFT_SUBTYPE_* */ |
1558 args->info.sendfile.subtype = aimbs_get16(servdata); | 1640 args->info.sendfile.subtype = aimbs_get16(servdata); |
1559 args->info.sendfile.totfiles = aimbs_get16(servdata); | 1641 args->info.sendfile.totfiles = aimbs_get16(servdata); |
1560 args->info.sendfile.totsize = aimbs_get32(servdata); | 1642 args->info.sendfile.totsize = aimbs_get32(servdata); |
1561 args->info.sendfile.filename = aimbs_getstr(servdata, | 1643 |
1562 servdata->len - (2+2+4+4)); | 1644 /* XXX - create an aimbs_getnullstr function */ |
1563 | 1645 /* Use an inelegant way of getting the null-terminated filename, |
1564 aimbs_get32(servdata); /* 0x00030000 (?) */ | 1646 * since there's no easy bstream routine. */ |
1647 for (flen = 0; aimbs_get8(servdata); flen++); | |
1648 aim_bstream_advance(servdata, -flen -1); | |
1649 args->info.sendfile.filename = aimbs_getstr(servdata, flen); | |
1650 | |
1651 /* There is sometimes more after the null-terminated filename, | |
1652 * but I'm unsure of its format. */ | |
1565 } | 1653 } |
1566 | 1654 |
1567 return; | 1655 return; |
1568 } | 1656 } |
1569 | 1657 |
1784 | 1872 |
1785 return ret; | 1873 return ret; |
1786 } | 1874 } |
1787 | 1875 |
1788 /* | 1876 /* |
1877 * Subtype 0x0007 | |
1878 * | |
1789 * It can easily be said that parsing ICBMs is THE single | 1879 * It can easily be said that parsing ICBMs is THE single |
1790 * most difficult thing to do in the in AIM protocol. In | 1880 * most difficult thing to do in the in AIM protocol. In |
1791 * fact, I think I just did say that. | 1881 * fact, I think I just did say that. |
1792 * | 1882 * |
1793 * Below is the best damned solution I've come up with | 1883 * Below is the best damned solution I've come up with |
1887 | 1977 |
1888 return ret; | 1978 return ret; |
1889 } | 1979 } |
1890 | 1980 |
1891 /* | 1981 /* |
1982 * Subtype 0x0008 - Send a warning to destsn. | |
1983 * | |
1984 * Flags: | |
1985 * AIM_WARN_ANON Send as an anonymous (doesn't count as much) | |
1986 * | |
1987 * returns -1 on error (couldn't alloc packet), 0 on success. | |
1988 * | |
1989 */ | |
1990 faim_export int aim_send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags) | |
1991 { | |
1992 aim_frame_t *fr; | |
1993 aim_snacid_t snacid; | |
1994 fu16_t outflags = 0x0000; | |
1995 | |
1996 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(destsn)+13))) | |
1997 return -ENOMEM; | |
1998 | |
1999 snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, destsn, strlen(destsn)+1); | |
2000 | |
2001 aim_putsnac(&fr->data, 0x0004, 0x0008, 0x0000, snacid); | |
2002 | |
2003 if (flags & AIM_WARN_ANON) | |
2004 outflags |= 0x0001; | |
2005 | |
2006 aimbs_put16(&fr->data, outflags); | |
2007 aimbs_put8(&fr->data, strlen(destsn)); | |
2008 aimbs_putraw(&fr->data, destsn, strlen(destsn)); | |
2009 | |
2010 aim_tx_enqueue(sess, fr); | |
2011 | |
2012 return 0; | |
2013 } | |
2014 | |
2015 /* Subtype 0x000a */ | |
2016 static int missedcall(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) | |
2017 { | |
2018 int ret = 0; | |
2019 aim_rxcallback_t userfunc; | |
2020 fu16_t channel, nummissed, reason; | |
2021 aim_userinfo_t userinfo; | |
2022 | |
2023 while (aim_bstream_empty(bs)) { | |
2024 | |
2025 channel = aimbs_get16(bs); | |
2026 aim_extractuserinfo(sess, bs, &userinfo); | |
2027 nummissed = aimbs_get16(bs); | |
2028 reason = aimbs_get16(bs); | |
2029 | |
2030 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | |
2031 ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); | |
2032 } | |
2033 | |
2034 return ret; | |
2035 } | |
2036 | |
2037 /* | |
2038 * Subtype 0x000b | |
2039 * | |
1892 * Possible codes: | 2040 * Possible codes: |
1893 * AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support" | 2041 * AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support" |
1894 * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer" | 2042 * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer" |
1895 * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers" | 2043 * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers" |
1896 * | 2044 * |
1925 | 2073 |
1926 return 0; | 2074 return 0; |
1927 } | 2075 } |
1928 | 2076 |
1929 /* | 2077 /* |
1930 * aim_reqicbmparaminfo() | 2078 * Subtype 0x000b - Receive the response from an ICQ status message request. |
1931 * | 2079 * |
1932 * Request ICBM parameter information. | 2080 * This contains the ICQ status message. Go figure. |
1933 * | 2081 * |
1934 */ | |
1935 faim_export int aim_reqicbmparams(aim_session_t *sess) | |
1936 { | |
1937 aim_conn_t *conn; | |
1938 | |
1939 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) | |
1940 return -EINVAL; | |
1941 | |
1942 return aim_genericreq_n(sess, conn, 0x0004, 0x0004); | |
1943 } | |
1944 | |
1945 /* | |
1946 * | |
1947 * I definitly recommend sending this. If you don't, you'll be stuck | |
1948 * with the rather unreasonable defaults. You don't want those. Send this. | |
1949 * | |
1950 */ | |
1951 faim_export int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params) | |
1952 { | |
1953 aim_conn_t *conn; | |
1954 aim_frame_t *fr; | |
1955 aim_snacid_t snacid; | |
1956 | |
1957 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) | |
1958 return -EINVAL; | |
1959 | |
1960 if (!params) | |
1961 return -EINVAL; | |
1962 | |
1963 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+16))) | |
1964 return -ENOMEM; | |
1965 | |
1966 snacid = aim_cachesnac(sess, 0x0004, 0x0002, 0x0000, NULL, 0); | |
1967 aim_putsnac(&fr->data, 0x0004, 0x0002, 0x0000, snacid); | |
1968 | |
1969 /* This is read-only (see Parameter Reply). Must be set to zero here. */ | |
1970 aimbs_put16(&fr->data, 0x0000); | |
1971 | |
1972 /* These are all read-write */ | |
1973 aimbs_put32(&fr->data, params->flags); | |
1974 aimbs_put16(&fr->data, params->maxmsglen); | |
1975 aimbs_put16(&fr->data, params->maxsenderwarn); | |
1976 aimbs_put16(&fr->data, params->maxrecverwarn); | |
1977 aimbs_put32(&fr->data, params->minmsginterval); | |
1978 | |
1979 aim_tx_enqueue(sess, fr); | |
1980 | |
1981 return 0; | |
1982 } | |
1983 | |
1984 static int paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) | |
1985 { | |
1986 struct aim_icbmparameters params; | |
1987 aim_rxcallback_t userfunc; | |
1988 | |
1989 params.maxchan = aimbs_get16(bs); | |
1990 params.flags = aimbs_get32(bs); | |
1991 params.maxmsglen = aimbs_get16(bs); | |
1992 params.maxsenderwarn = aimbs_get16(bs); | |
1993 params.maxrecverwarn = aimbs_get16(bs); | |
1994 params.minmsginterval = aimbs_get32(bs); | |
1995 | |
1996 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | |
1997 return userfunc(sess, rx, ¶ms); | |
1998 | |
1999 return 0; | |
2000 } | |
2001 | |
2002 static int missedcall(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) | |
2003 { | |
2004 int ret = 0; | |
2005 aim_rxcallback_t userfunc; | |
2006 fu16_t channel, nummissed, reason; | |
2007 aim_userinfo_t userinfo; | |
2008 | |
2009 while (aim_bstream_empty(bs)) { | |
2010 | |
2011 channel = aimbs_get16(bs); | |
2012 aim_extractuserinfo(sess, bs, &userinfo); | |
2013 nummissed = aimbs_get16(bs); | |
2014 reason = aimbs_get16(bs); | |
2015 | |
2016 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | |
2017 ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); | |
2018 } | |
2019 | |
2020 return ret; | |
2021 } | |
2022 | |
2023 /* | |
2024 * Receive the response from an ICQ status message request. This contains the | |
2025 * ICQ status message. Go figure. | |
2026 */ | 2082 */ |
2027 static int clientautoresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) | 2083 static int clientautoresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
2028 { | 2084 { |
2029 int ret = 0; | 2085 int ret = 0; |
2030 aim_rxcallback_t userfunc; | 2086 aim_rxcallback_t userfunc; |
2036 channel = aimbs_get16(bs); | 2092 channel = aimbs_get16(bs); |
2037 snlen = aimbs_get8(bs); | 2093 snlen = aimbs_get8(bs); |
2038 sn = aimbs_getstr(bs, snlen); | 2094 sn = aimbs_getstr(bs, snlen); |
2039 reason = aimbs_get16(bs); | 2095 reason = aimbs_get16(bs); |
2040 | 2096 |
2041 if (channel == 2) { | 2097 if (channel == 0x0002) { /* File transfer declined */ |
2042 /* File transfer declined. */ | |
2043 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 2098 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
2044 ret = userfunc(sess, rx, channel, sn, reason, ck); | 2099 ret = userfunc(sess, rx, channel, sn, reason, ck); |
2045 | 2100 } else if (channel == 0x0004) { /* ICQ message */ |
2046 free(sn); | 2101 switch (reason) { |
2047 free(ck); | 2102 case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */ |
2048 return ret; | 2103 fu8_t statusmsgtype, *msg; |
2049 } | 2104 fu16_t len; |
2050 | 2105 fu32_t state; |
2051 switch (reason) { | 2106 |
2052 case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */ | 2107 len = aimbs_getle16(bs); /* Should be 0x001b */ |
2053 fu8_t statusmsgtype, *msg; | 2108 aim_bstream_advance(bs, len); /* Unknown */ |
2054 fu16_t len; | 2109 |
2055 fu32_t state; | 2110 len = aimbs_getle16(bs); /* Should be 0x000e */ |
2056 | 2111 aim_bstream_advance(bs, len); /* Unknown */ |
2057 len = aimbs_getle16(bs); /* Should be 0x001b */ | 2112 |
2058 aim_bstream_advance(bs, len); /* Unknown */ | 2113 statusmsgtype = aimbs_getle8(bs); |
2059 | 2114 switch (statusmsgtype) { |
2060 len = aimbs_getle16(bs); /* Should be 0x000e */ | 2115 case 0xe8: |
2061 aim_bstream_advance(bs, len); /* Unknown */ | 2116 state = AIM_ICQ_STATE_AWAY; |
2062 | 2117 break; |
2063 statusmsgtype = aimbs_getle8(bs); | 2118 case 0xe9: |
2064 switch (statusmsgtype) { | 2119 state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY; |
2065 case 0xe8: | 2120 break; |
2066 state = AIM_ICQ_STATE_AWAY; | 2121 case 0xea: |
2067 break; | 2122 state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT; |
2068 case 0xe9: | 2123 break; |
2069 state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY; | 2124 case 0xeb: |
2070 break; | 2125 state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY; |
2071 case 0xea: | 2126 break; |
2072 state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT; | 2127 case 0xec: |
2073 break; | 2128 state = AIM_ICQ_STATE_CHAT; |
2074 case 0xeb: | 2129 break; |
2075 state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY; | 2130 default: |
2076 break; | 2131 state = 0; |
2077 case 0xec: | 2132 break; |
2078 state = AIM_ICQ_STATE_CHAT; | 2133 } |
2079 break; | 2134 |
2080 default: | 2135 aimbs_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */ |
2081 state = 0; | 2136 aimbs_getle16(bs); /* Unknown - 0x0000 */ |
2082 break; | 2137 aimbs_getle16(bs); /* Unknown - 0x0000 */ |
2083 } | 2138 |
2084 | 2139 len = aimbs_getle16(bs); |
2085 aimbs_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */ | 2140 msg = aimbs_getraw(bs, len); |
2086 aimbs_getle16(bs); /* Unknown - 0x0000 */ | 2141 |
2087 aimbs_getle16(bs); /* Unknown - 0x0000 */ | 2142 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
2088 | 2143 ret = userfunc(sess, rx, channel, sn, reason, state, msg); |
2089 len = aimbs_getle16(bs); | 2144 |
2090 msg = aimbs_getraw(bs, len); | 2145 free(msg); |
2091 | 2146 } break; |
2092 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | 2147 |
2093 ret = userfunc(sess, rx, channel, sn, reason, state, msg); | 2148 default: { |
2094 | 2149 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) |
2095 free(msg); | 2150 ret = userfunc(sess, rx, channel, sn, reason); |
2096 } break; | 2151 } break; |
2097 | 2152 } /* end switch */ |
2098 default: { | 2153 } |
2099 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) | |
2100 ret = userfunc(sess, rx, channel, sn, reason); | |
2101 } break; | |
2102 } /* end switch */ | |
2103 | 2154 |
2104 free(ck); | 2155 free(ck); |
2105 free(sn); | 2156 free(sn); |
2106 | 2157 |
2107 return ret; | 2158 return ret; |
2108 } | 2159 } |
2109 | 2160 |
2161 /* Subtype 0x000c */ | |
2110 static int msgack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) | 2162 static int msgack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
2111 { | 2163 { |
2112 aim_rxcallback_t userfunc; | 2164 aim_rxcallback_t userfunc; |
2113 fu16_t type; | 2165 fu16_t type; |
2114 fu8_t snlen, *ck; | 2166 fu8_t snlen, *ck; |
2128 | 2180 |
2129 return ret; | 2181 return ret; |
2130 } | 2182 } |
2131 | 2183 |
2132 /* | 2184 /* |
2133 * Send a mini typing notification (mtn) packet. This is supported by winaim 5 and up. | 2185 * Subtype 0x0014 - Send a mini typing notification (mtn) packet. |
2186 * | |
2187 * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, | |
2188 * and Gaim 0.60 and newer. | |
2189 * | |
2134 */ | 2190 */ |
2135 faim_export int aim_mtn_send(aim_session_t *sess, fu16_t type1, char *sn, fu16_t type2) | 2191 faim_export int aim_mtn_send(aim_session_t *sess, fu16_t type1, char *sn, fu16_t type2) |
2136 { | 2192 { |
2137 aim_conn_t *conn; | 2193 aim_conn_t *conn; |
2138 aim_frame_t *fr; | 2194 aim_frame_t *fr; |
2179 | 2235 |
2180 return 0; | 2236 return 0; |
2181 } | 2237 } |
2182 | 2238 |
2183 /* | 2239 /* |
2184 * Receive a mini typing notification (mtn) packet. This is supported by winaim5 and up. | 2240 * Subtype 0x0014 - Receive a mini typing notification (mtn) packet. |
2241 * | |
2242 * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, | |
2243 * and Gaim 0.60 and newer. | |
2244 * | |
2185 */ | 2245 */ |
2186 static int mtn_receive(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) | 2246 static int mtn_receive(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) |
2187 { | 2247 { |
2188 int ret = 0; | 2248 int ret = 0; |
2189 aim_rxcallback_t userfunc; | 2249 aim_rxcallback_t userfunc; |
2237 } | 2297 } |
2238 /* Note that we return 1 for success, 0 for failure. */ | 2298 /* Note that we return 1 for success, 0 for failure. */ |
2239 return ret; | 2299 return ret; |
2240 } | 2300 } |
2241 | 2301 |
2242 | |
2243 faim_internal int msg_modfirst(aim_session_t *sess, aim_module_t *mod) | 2302 faim_internal int msg_modfirst(aim_session_t *sess, aim_module_t *mod) |
2244 { | 2303 { |
2245 | 2304 |
2246 mod->family = 0x0004; | 2305 mod->family = 0x0004; |
2247 mod->version = 0x0001; | 2306 mod->version = 0x0001; |