src/protocols/oscar/im.c

changeset 3141
3adc8022a85f
parent 2869
3165d3aff6c0
child 3159
15816c95c61c
equal deleted inserted replaced
3140:168c622ed90d 3141:3adc8022a85f
724 aimbs_put32(&fr->data, totsize); 724 aimbs_put32(&fr->data, totsize);
725 aimbs_putraw(&fr->data, filename, strlen(filename)); 725 aimbs_putraw(&fr->data, filename, strlen(filename));
726 726
727 /* ? */ 727 /* ? */
728 aimbs_put32(&fr->data, 0x00000000); 728 aimbs_put32(&fr->data, 0x00000000);
729
730 aim_tx_enqueue(sess, fr);
731
732 return 0;
733 }
734
735 /*
736 * This can be used to send an ICQ authorization reply (deny or grant). It is the "old way."
737 * The new way is to use SSI. I like the new way a lot better. This seems like such a hack,
738 * mostly because it's in network byte order. Figuring this stuff out sometimes takes a while,
739 * but thats ok, because it gives me time to try to figure out what kind of drugs the AOL people
740 * were taking when they merged the two protocols.
741 *
742 * sn is the destination screen name
743 * type is the type of message. 0x0007 for authorization denied. 0x0008 for authorization granted
744 * message is the message you want to send, it should be null terminated
745 */
746 faim_export int aim_send_im_ch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message)
747 {
748 aim_conn_t *conn;
749 aim_frame_t *fr;
750 aim_snacid_t snacid;
751 int i;
752
753 if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002)))
754 return -EINVAL;
755
756 if (!sn || !type || !message)
757 return -EINVAL;
758
759 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+8+3+strlen(sn)+12+strlen(message)+1+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 /*
766 * Cookie
767 */
768 for (i=0; i<8; i++)
769 aimbs_put8(&fr->data, (fu8_t)rand());
770
771 /*
772 * Channel (4)
773 */
774 aimbs_put16(&fr->data, 0x0004);
775
776 /*
777 * Dest sn
778 */
779 aimbs_put8(&fr->data, strlen(sn));
780 aimbs_putraw(&fr->data, sn, strlen(sn));
781
782 /*
783 * TLV t(0005)
784 *
785 * ICQ data (the UIN and the message).
786 */
787 aimbs_put16(&fr->data, 0x0005);
788 aimbs_put16(&fr->data, 4 + 2+2+strlen(message)+1);
789
790 /*
791 * Your UIN
792 */
793 aimbs_putle32(&fr->data, atoi(sess->sn));
794
795 /*
796 * TLV t(type) l(strlen(message)+1) v(message+NULL)
797 */
798 aimbs_putle16(&fr->data, type);
799 aimbs_putle16(&fr->data, strlen(message)+1);
800 aimbs_putraw(&fr->data, message, strlen(message)+1);
801
802 /*
803 * TLV t(0006) l(0000) v()
804 */
805 aimbs_put16(&fr->data, 0x0006);
806 aimbs_put16(&fr->data, 0x0000);
729 807
730 aim_tx_enqueue(sess, fr); 808 aim_tx_enqueue(sess, fr);
731 809
732 return 0; 810 return 0;
733 } 811 }
1517 aim_freetlvchain(&list2); 1595 aim_freetlvchain(&list2);
1518 1596
1519 return ret; 1597 return ret;
1520 } 1598 }
1521 1599
1600 static int incomingim_ch4(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie)
1601 {
1602 aim_bstream_t meat;
1603 aim_rxcallback_t userfunc;
1604 aim_tlv_t *block;
1605 struct aim_incomingim_ch4_args args;
1606 int ret;
1607
1608 /*
1609 * Make a bstream for the meaty part. Yum. Meat.
1610 */
1611 if (!(block = aim_gettlv(tlvlist, 0x0005, 1)))
1612 return -1;
1613 aim_bstream_init(&meat, block->value, block->length);
1614
1615 args.uin = aimbs_getle32(&meat);
1616 args.type = aimbs_getle16(&meat);
1617 args.msg = aimbs_getraw(&meat, aimbs_getle16(&meat));
1618
1619 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
1620 ret = userfunc(sess, rx, channel, userinfo, &args);
1621
1622 free(args.msg);
1623
1624 return ret;
1625 }
1626
1522 /* 1627 /*
1523 * It can easily be said that parsing ICBMs is THE single 1628 * It can easily be said that parsing ICBMs is THE single
1524 * most difficult thing to do in the in AIM protocol. In 1629 * most difficult thing to do in the in AIM protocol. In
1525 * fact, I think I just did say that. 1630 * fact, I think I just did say that.
1526 * 1631 *
1554 * features of AIM2/3/3.5. 1659 * features of AIM2/3/3.5.
1555 * 1660 *
1556 * Channel 0x0002 is the Rendevous channel, which 1661 * Channel 0x0002 is the Rendevous channel, which
1557 * is where Chat Invitiations and various client-client 1662 * is where Chat Invitiations and various client-client
1558 * connection negotiations come from. 1663 * connection negotiations come from.
1559 * 1664 *
1665 * Channel 0x0004 is used for ICQ authorization, or
1666 * possibly any system notice.
1667 *
1560 */ 1668 */
1561 channel = aimbs_get16(bs); 1669 channel = aimbs_get16(bs);
1562 1670
1563 /* 1671 /*
1564 * Extract the standard user info block. 1672 * Extract the standard user info block.
1598 */ 1706 */
1599 tlvlist = aim_readtlvchain(bs); 1707 tlvlist = aim_readtlvchain(bs);
1600 1708
1601 ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie); 1709 ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
1602 1710
1711 aim_freetlvchain(&tlvlist);
1712
1713 } else if (channel == 4) {
1714 aim_tlvlist_t *tlvlist;
1715
1716 tlvlist = aim_readtlvchain(bs);
1717 ret = incomingim_ch4(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
1603 aim_freetlvchain(&tlvlist); 1718 aim_freetlvchain(&tlvlist);
1604 1719
1605 } else { 1720 } else {
1606 1721
1607 faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel. Ignoring.\n (chan = %04x)", channel); 1722 faimdprintf(sess, 0, "icbm: ICBM received on an unsupported channel. Ignoring.\n (chan = %04x)", channel);

mercurial