Changes in protocols/oscar/im.c [d18db32f:6042a54]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/oscar/im.c
rd18db32f r6042a54 23 23 #include "im.h" 24 24 #include "info.h" 25 26 /*27 * Takes a msghdr (and a length) and returns a client type28 * code. Note that this is *only a guess* and has a low likelihood29 * of actually being accurate.30 *31 * Its based on experimental data, with the help of Eric Warmenhoven32 * who seems to have collected a wide variety of different AIM clients.33 *34 *35 * Heres the current collection:36 * 0501 0003 0101 0101 01 AOL Mobile Communicator, WinAIM 1.0.41437 * 0501 0003 0101 0201 01 WinAIM 2.0.847, 2.1.1187, 3.0.1464,38 * 4.3.2229, 4.4.228639 * 0501 0004 0101 0102 0101 WinAIM 4.1.2010, libfaim (right here)40 * 0501 0001 0101 01 AOL v6.0, CompuServe 2000 v6.0, any41 * TOC client42 *43 * Note that in this function, only the feature bytes are tested, since44 * the rest will always be the same.45 *46 */47 guint16 aim_fingerprintclient(guint8 *msghdr, int len)48 {49 static const struct {50 guint16 clientid;51 int len;52 guint8 data[10];53 } fingerprints[] = {54 /* AOL Mobile Communicator, WinAIM 1.0.414 */55 { AIM_CLIENTTYPE_MC,56 3, {0x01, 0x01, 0x01}},57 58 /* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */59 { AIM_CLIENTTYPE_WINAIM,60 3, {0x01, 0x01, 0x02}},61 62 /* WinAIM 4.1.2010, libfaim */63 { AIM_CLIENTTYPE_WINAIM41,64 4, {0x01, 0x01, 0x01, 0x02}},65 66 /* AOL v6.0, CompuServe 2000 v6.0, any TOC client */67 { AIM_CLIENTTYPE_AOL_TOC,68 1, {0x01}},69 70 { 0, 0}71 };72 int i;73 74 if (!msghdr || (len <= 0))75 return AIM_CLIENTTYPE_UNKNOWN;76 77 for (i = 0; fingerprints[i].len; i++) {78 if (fingerprints[i].len != len)79 continue;80 if (memcmp(fingerprints[i].data, msghdr, fingerprints[i].len) == 0)81 return fingerprints[i].clientid;82 }83 84 return AIM_CLIENTTYPE_UNKNOWN;85 }86 87 /* This should be endian-safe now... but who knows... */88 guint16 aim_iconsum(const guint8 *buf, int buflen)89 {90 guint32 sum;91 int i;92 93 for (i = 0, sum = 0; i + 1 < buflen; i += 2)94 sum += (buf[i+1] << 8) + buf[i];95 if (i < buflen)96 sum += buf[i];97 98 sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);99 100 return (guint16)sum;101 }102 25 103 26 /* … … 367 290 } 368 291 369 /*370 * This is also performance sensitive. (If you can believe it...)371 *372 */373 int aim_send_icon(aim_session_t *sess, const char *sn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum)374 {375 aim_conn_t *conn;376 int i;377 guint8 ck[8];378 aim_frame_t *fr;379 aim_snacid_t snacid;380 381 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))382 return -EINVAL;383 384 if (!sn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN))385 return -EINVAL;386 387 for (i = 0; i < 8; i++)388 aimutil_put8(ck+i, (guint8) rand());389 390 if (!(fr = aim_tx_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)))391 return -ENOMEM;392 393 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);394 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);395 396 /*397 * Cookie398 */399 aimbs_putraw(&fr->data, ck, 8);400 401 /*402 * Channel (2)403 */404 aimbs_put16(&fr->data, 0x0002);405 406 /*407 * Dest sn408 */409 aimbs_put8(&fr->data, strlen(sn));410 aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn));411 412 /*413 * TLV t(0005)414 *415 * Encompasses everything below.416 */417 aimbs_put16(&fr->data, 0x0005);418 aimbs_put16(&fr->data, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT));419 420 aimbs_put16(&fr->data, 0x0000);421 aimbs_putraw(&fr->data, ck, 8);422 aim_putcap(&fr->data, AIM_CAPS_BUDDYICON);423 424 /* TLV t(000a) */425 aimbs_put16(&fr->data, 0x000a);426 aimbs_put16(&fr->data, 0x0002);427 aimbs_put16(&fr->data, 0x0001);428 429 /* TLV t(000f) */430 aimbs_put16(&fr->data, 0x000f);431 aimbs_put16(&fr->data, 0x0000);432 433 /* TLV t(2711) */434 aimbs_put16(&fr->data, 0x2711);435 aimbs_put16(&fr->data, 4+4+4+iconlen+strlen(AIM_ICONIDENT));436 aimbs_put16(&fr->data, 0x0000);437 aimbs_put16(&fr->data, iconsum);438 aimbs_put32(&fr->data, iconlen);439 aimbs_put32(&fr->data, stamp);440 aimbs_putraw(&fr->data, icon, iconlen);441 aimbs_putraw(&fr->data, (guint8 *)AIM_ICONIDENT, strlen(AIM_ICONIDENT));442 443 /* TLV t(0003) */444 aimbs_put16(&fr->data, 0x0003);445 aimbs_put16(&fr->data, 0x0000);446 447 aim_tx_enqueue(sess, fr);448 449 return 0;450 }451 452 /*453 * This only works for ICQ 2001b (thats 2001 not 2000). Better, only454 * send it to clients advertising the RTF capability. In fact, if you send455 * it to a client that doesn't support that capability, the server will gladly456 * bounce it back to you.457 *458 * You'd think this would be in icq.c, but, well, I'm trying to stick with459 * the one-group-per-file scheme as much as possible. This could easily460 * be an exception, since Rendezvous IMs are external of the Oscar core,461 * and therefore are undefined. Really I just need to think of a good way to462 * make an interface similar to what AOL actually uses. But I'm not using COM.463 *464 */465 int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args)466 {467 const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* AIM_CAPS_ICQRTF capability in string form */468 aim_conn_t *conn;469 int i;470 guint8 ck[8];471 aim_frame_t *fr;472 aim_snacid_t snacid;473 int servdatalen;474 475 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))476 return -EINVAL;477 478 if (!args || !args->destsn || !args->rtfmsg)479 return -EINVAL;480 481 servdatalen = 2+2+16+2+4+1+2 + 2+2+4+4+4 + 2+4+2+strlen(args->rtfmsg)+1 + 4+4+4+strlen(rtfcap)+1;482 483 for (i = 0; i < 8; i++)484 aimutil_put8(ck+i, (guint8) rand());485 486 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+128+servdatalen)))487 return -ENOMEM;488 489 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);490 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);491 492 /*493 * Cookie494 */495 aimbs_putraw(&fr->data, ck, 8);496 497 /*498 * Channel (2)499 */500 aimbs_put16(&fr->data, 0x0002);501 502 /*503 * Dest sn504 */505 aimbs_put8(&fr->data, strlen(args->destsn));506 aimbs_putraw(&fr->data, (guint8 *)args->destsn, strlen(args->destsn));507 508 /*509 * TLV t(0005)510 *511 * Encompasses everything below.512 */513 aimbs_put16(&fr->data, 0x0005);514 aimbs_put16(&fr->data, 2+8+16 + 2+2+2 + 2+2 + 2+2+servdatalen);515 516 aimbs_put16(&fr->data, 0x0000);517 aimbs_putraw(&fr->data, ck, 8);518 aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY);519 520 /*521 * t(000a) l(0002) v(0001)522 */523 aimbs_put16(&fr->data, 0x000a);524 aimbs_put16(&fr->data, 0x0002);525 aimbs_put16(&fr->data, 0x0001);526 527 /*528 * t(000f) l(0000) v()529 */530 aimbs_put16(&fr->data, 0x000f);531 aimbs_put16(&fr->data, 0x0000);532 533 /*534 * Service Data TLV535 */536 aimbs_put16(&fr->data, 0x2711);537 aimbs_put16(&fr->data, servdatalen);538 539 aimbs_putle16(&fr->data, 11 + 16 /* 11 + (sizeof CLSID) */);540 aimbs_putle16(&fr->data, 9);541 aim_putcap(&fr->data, AIM_CAPS_EMPTY);542 aimbs_putle16(&fr->data, 0);543 aimbs_putle32(&fr->data, 0);544 aimbs_putle8(&fr->data, 0);545 aimbs_putle16(&fr->data, 0x03ea); /* trid1 */546 547 aimbs_putle16(&fr->data, 14);548 aimbs_putle16(&fr->data, 0x03eb); /* trid2 */549 aimbs_putle32(&fr->data, 0);550 aimbs_putle32(&fr->data, 0);551 aimbs_putle32(&fr->data, 0);552 553 aimbs_putle16(&fr->data, 0x0001);554 aimbs_putle32(&fr->data, 0);555 aimbs_putle16(&fr->data, strlen(args->rtfmsg)+1);556 aimbs_putraw(&fr->data, (guint8 *)args->rtfmsg, strlen(args->rtfmsg)+1);557 558 aimbs_putle32(&fr->data, args->fgcolor);559 aimbs_putle32(&fr->data, args->bgcolor);560 aimbs_putle32(&fr->data, strlen(rtfcap)+1);561 aimbs_putraw(&fr->data, (guint8 *)rtfcap, strlen(rtfcap)+1);562 563 aim_tx_enqueue(sess, fr);564 565 return 0;566 }567 568 int aim_request_directim(aim_session_t *sess, const char *destsn, guint8 *ip, guint16 port, guint8 *ckret)569 {570 aim_conn_t *conn;571 guint8 ck[8];572 aim_frame_t *fr;573 aim_snacid_t snacid;574 aim_tlvlist_t *tl = NULL, *itl = NULL;575 int hdrlen, i;576 guint8 *hdr;577 aim_bstream_t hdrbs;578 579 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))580 return -EINVAL;581 582 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 256+strlen(destsn))))583 return -ENOMEM;584 585 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);586 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);587 588 /*589 * Generate a random message cookie590 *591 * This cookie needs to be alphanumeric and NULL-terminated to be592 * TOC-compatible.593 *594 * XXX have I mentioned these should be generated in msgcookie.c?595 *596 */597 for (i = 0; i < 7; i++)598 ck[i] = 0x30 + ((guint8) rand() % 10);599 ck[7] = '\0';600 601 if (ckret)602 memcpy(ckret, ck, 8);603 604 /* Cookie */605 aimbs_putraw(&fr->data, ck, 8);606 607 /* Channel */608 aimbs_put16(&fr->data, 0x0002);609 610 /* Destination SN */611 aimbs_put8(&fr->data, strlen(destsn));612 aimbs_putraw(&fr->data, (guint8 *)destsn, strlen(destsn));613 614 aim_addtlvtochain_noval(&tl, 0x0003);615 616 hdrlen = 2+8+16+6+8+6+4;617 hdr = g_malloc(hdrlen);618 aim_bstream_init(&hdrbs, hdr, hdrlen);619 620 aimbs_put16(&hdrbs, 0x0000);621 aimbs_putraw(&hdrbs, ck, 8);622 aim_putcap(&hdrbs, AIM_CAPS_IMIMAGE);623 624 aim_addtlvtochain16(&itl, 0x000a, 0x0001);625 aim_addtlvtochain_raw(&itl, 0x0003, 4, ip);626 aim_addtlvtochain16(&itl, 0x0005, port);627 aim_addtlvtochain_noval(&itl, 0x000f);628 629 aim_writetlvchain(&hdrbs, &itl);630 631 aim_addtlvtochain_raw(&tl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);632 633 aim_writetlvchain(&fr->data, &tl);634 635 g_free(hdr);636 aim_freetlvchain(&itl);637 aim_freetlvchain(&tl);638 639 aim_tx_enqueue(sess, fr);640 641 return 0;642 }643 644 int aim_request_sendfile(aim_session_t *sess, const char *sn, const char *filename, guint16 numfiles, guint32 totsize, guint8 *ip, guint16 port, guint8 *ckret)645 {646 aim_conn_t *conn;647 int i;648 guint8 ck[8];649 aim_frame_t *fr;650 aim_snacid_t snacid;651 652 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))653 return -EINVAL;654 655 if (!sn || !filename)656 return -EINVAL;657 658 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn)+2+2+2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4)))659 return -ENOMEM;660 661 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);662 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);663 664 for (i = 0; i < 7; i++)665 aimutil_put8(ck+i, 0x30 + ((guint8) rand() % 10));666 ck[7] = '\0';667 668 if (ckret)669 memcpy(ckret, ck, 8);670 671 /*672 * Cookie673 */674 aimbs_putraw(&fr->data, ck, 8);675 676 /*677 * Channel (2)678 */679 aimbs_put16(&fr->data, 0x0002);680 681 /*682 * Dest sn683 */684 aimbs_put8(&fr->data, strlen(sn));685 aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn));686 687 /*688 * TLV t(0005)689 *690 * Encompasses everything below. Gee.691 */692 aimbs_put16(&fr->data, 0x0005);693 aimbs_put16(&fr->data, 2+8+16+6+8+6+4+2+2+2+2+4+strlen(filename)+4);694 695 aimbs_put16(&fr->data, 0x0000);696 aimbs_putraw(&fr->data, ck, 8);697 aim_putcap(&fr->data, AIM_CAPS_SENDFILE);698 699 /* TLV t(000a) */700 aimbs_put16(&fr->data, 0x000a);701 aimbs_put16(&fr->data, 0x0002);702 aimbs_put16(&fr->data, 0x0001);703 704 /* TLV t(0003) (IP) */705 aimbs_put16(&fr->data, 0x0003);706 aimbs_put16(&fr->data, 0x0004);707 aimbs_putraw(&fr->data, ip, 4);708 709 /* TLV t(0005) (port) */710 aimbs_put16(&fr->data, 0x0005);711 aimbs_put16(&fr->data, 0x0002);712 aimbs_put16(&fr->data, port);713 714 /* TLV t(000f) */715 aimbs_put16(&fr->data, 0x000f);716 aimbs_put16(&fr->data, 0x0000);717 718 /* TLV t(2711) */719 aimbs_put16(&fr->data, 0x2711);720 aimbs_put16(&fr->data, 2+2+4+strlen(filename)+4);721 722 /* ? */723 aimbs_put16(&fr->data, 0x0001);724 aimbs_put16(&fr->data, numfiles);725 aimbs_put32(&fr->data, totsize);726 aimbs_putraw(&fr->data, (guint8 *)filename, strlen(filename));727 728 /* ? */729 aimbs_put32(&fr->data, 0x00000000);730 731 aim_tx_enqueue(sess, fr);732 733 return 0;734 }735 736 /**737 * Request the status message of the given ICQ user.738 *739 * @param sess The oscar session.740 * @param sn The UIN of the user of whom you wish to request info.741 * @param type The type of info you wish to request. This should be the current742 * state of the user, as one of the AIM_ICQ_STATE_* defines.743 * @return Return 0 if no errors, otherwise return the error number.744 */745 int aim_send_im_ch2_geticqmessage(aim_session_t *sess, const char *sn, int type)746 {747 aim_conn_t *conn;748 int i;749 guint8 ck[8];750 aim_frame_t *fr;751 aim_snacid_t snacid;752 753 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !sn)754 return -EINVAL;755 756 for (i = 0; i < 8; i++)757 aimutil_put8(ck+i, (guint8) rand());758 759 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sn) + 4+0x5e + 4)))760 return -ENOMEM;761 762 snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0);763 aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);764 765 /* Cookie */766 aimbs_putraw(&fr->data, ck, 8);767 768 /* Channel (2) */769 aimbs_put16(&fr->data, 0x0002);770 771 /* Dest sn */772 aimbs_put8(&fr->data, strlen(sn));773 aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn));774 775 /* TLV t(0005) - Encompasses almost everything below. */776 aimbs_put16(&fr->data, 0x0005); /* T */777 aimbs_put16(&fr->data, 0x005e); /* L */778 { /* V */779 aimbs_put16(&fr->data, 0x0000);780 781 /* Cookie */782 aimbs_putraw(&fr->data, ck, 8);783 784 /* Put the 16 byte server relay capability */785 aim_putcap(&fr->data, AIM_CAPS_ICQSERVERRELAY);786 787 /* TLV t(000a) */788 aimbs_put16(&fr->data, 0x000a);789 aimbs_put16(&fr->data, 0x0002);790 aimbs_put16(&fr->data, 0x0001);791 792 /* TLV t(000f) */793 aimbs_put16(&fr->data, 0x000f);794 aimbs_put16(&fr->data, 0x0000);795 796 /* TLV t(2711) */797 aimbs_put16(&fr->data, 0x2711);798 aimbs_put16(&fr->data, 0x0036);799 { /* V */800 aimbs_putle16(&fr->data, 0x001b); /* L */801 aimbs_putle16(&fr->data, 0x0008); /* AAA - Protocol version */802 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */803 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */804 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */805 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */806 aimbs_putle16(&fr->data, 0x0000); /* Unknown */807 aimbs_putle16(&fr->data, 0x0003); /* Client features? */808 aimbs_putle16(&fr->data, 0x0000); /* Unknown */809 aimbs_putle8(&fr->data, 0x00); /* Unkizown */810 aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */811 812 aimbs_putle16(&fr->data, 0x000e); /* L */813 aimbs_putle16(&fr->data, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */814 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */815 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */816 aimbs_putle32(&fr->data, 0x00000000); /* Unknown */817 818 /* The type of status message being requested */819 if (type & AIM_ICQ_STATE_CHAT)820 aimbs_putle16(&fr->data, 0x03ec);821 else if(type & AIM_ICQ_STATE_DND)822 aimbs_putle16(&fr->data, 0x03eb);823 else if(type & AIM_ICQ_STATE_OUT)824 aimbs_putle16(&fr->data, 0x03ea);825 else if(type & AIM_ICQ_STATE_BUSY)826 aimbs_putle16(&fr->data, 0x03e9);827 else if(type & AIM_ICQ_STATE_AWAY)828 aimbs_putle16(&fr->data, 0x03e8);829 830 aimbs_putle16(&fr->data, 0x0000); /* Status? */831 aimbs_putle16(&fr->data, 0x0001); /* Priority of this message? */832 aimbs_putle16(&fr->data, 0x0001); /* L? */833 aimbs_putle8(&fr->data, 0x00); /* Null termination? */834 } /* End TLV t(2711) */835 } /* End TLV t(0005) */836 837 /* TLV t(0003) */838 aimbs_put16(&fr->data, 0x0003);839 aimbs_put16(&fr->data, 0x0000);840 841 aim_tx_enqueue(sess, fr);842 843 return 0;844 }845 846 292 /** 847 293 * answers status message requests … … 1050 496 mpm->numparts++; 1051 497 1052 return 0;1053 }1054 1055 int aim_mpmsg_addraw(aim_session_t *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const guint8 *data, guint16 datalen)1056 {1057 guint8 *dup;1058 1059 if (!(dup = g_malloc(datalen)))1060 return -1;1061 memcpy(dup, data, datalen);1062 1063 if (mpmsg_addsection(sess, mpm, charset, charsubset, dup, datalen) == -1) {1064 g_free(dup);1065 return -1;1066 }1067 1068 return 0;1069 }1070 1071 /* XXX should provide a way of saying ISO-8859-1 specifically */1072 int aim_mpmsg_addascii(aim_session_t *sess, aim_mpmsg_t *mpm, const char *ascii)1073 {1074 char *dup;1075 1076 if (!(dup = g_strdup(ascii)))1077 return -1;1078 1079 if (mpmsg_addsection(sess, mpm, 0x0000, 0x0000, (guint8 *)dup, (guint16) strlen(ascii)) == -1) {1080 g_free(dup);1081 return -1;1082 }1083 1084 return 0;1085 }1086 1087 int aim_mpmsg_addunicode(aim_session_t *sess, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen)1088 {1089 guint8 *buf;1090 aim_bstream_t bs;1091 int i;1092 1093 if (!(buf = g_malloc(unicodelen * 2)))1094 return -1;1095 1096 aim_bstream_init(&bs, buf, unicodelen * 2);1097 1098 /* We assume unicode is in /host/ byte order -- convert to network */1099 for (i = 0; i < unicodelen; i++)1100 aimbs_put16(&bs, unicode[i]);1101 1102 if (mpmsg_addsection(sess, mpm, 0x0002, 0x0000, buf, aim_bstream_curpos(&bs)) == -1) {1103 g_free(buf);1104 return -1;1105 }1106 1107 498 return 0; 1108 499 } … … 1788 1179 1789 1180 return ret; 1790 }1791 1792 /*1793 * Possible codes:1794 * AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support"1795 * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer"1796 * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers"1797 *1798 */1799 int aim_denytransfer(aim_session_t *sess, const char *sender, const guint8 *cookie, guint16 code)1800 {1801 aim_conn_t *conn;1802 aim_frame_t *fr;1803 aim_snacid_t snacid;1804 aim_tlvlist_t *tl = NULL;1805 1806 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)))1807 return -EINVAL;1808 1809 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+2+1+strlen(sender)+6)))1810 return -ENOMEM;1811 1812 snacid = aim_cachesnac(sess, 0x0004, 0x000b, 0x0000, NULL, 0);1813 aim_putsnac(&fr->data, 0x0004, 0x000b, 0x0000, snacid);1814 1815 aimbs_putraw(&fr->data, cookie, 8);1816 1817 aimbs_put16(&fr->data, 0x0002); /* channel */1818 aimbs_put8(&fr->data, strlen(sender));1819 aimbs_putraw(&fr->data, (guint8 *)sender, strlen(sender));1820 1821 aim_addtlvtochain16(&tl, 0x0003, code);1822 aim_writetlvchain(&fr->data, &tl);1823 aim_freetlvchain(&tl);1824 1825 aim_tx_enqueue(sess, fr);1826 1827 return 0;1828 1181 } 1829 1182
Note: See TracChangeset
for help on using the changeset viewer.