comparison libpurple/protocols/oscar/family_oservice.c @ 22717:979a81468e19

All SNACs on FLAP channel 2 except in the auth family are now sent through flap_connection_send_snac() instead of flap_connection_send(). This allows them to be tallied into the rate limiting calculations and to be throttled as necessary to prevent rate limiting violations. This does fix the instantaneous disconnection seen with the addition of ICQ Status Notes support for people with many ICQ contacts with status notes on their buddy list. Unfortunately, we still request the ICQ Status Note many times per contact, so such people now may be rate limited for a significant period of time as they connect.
author Evan Schoenberg <evan.s@dreskin.net>
date Thu, 24 Apr 2008 11:10:03 +0000
parents 3225c99785b8
children ab2322195dab
comparison
equal deleted inserted replaced
22715:80c87908ff1d 22717:979a81468e19
29 29
30 /* Subtype 0x0002 - Client Online */ 30 /* Subtype 0x0002 - Client Online */
31 void 31 void
32 aim_clientready(OscarData *od, FlapConnection *conn) 32 aim_clientready(OscarData *od, FlapConnection *conn)
33 { 33 {
34 FlapFrame *frame; 34 ByteStream bs;
35 aim_snacid_t snacid; 35 aim_snacid_t snacid;
36 GSList *cur; 36 GSList *cur;
37 37
38 frame = flap_frame_new(od, 0x02, 1152); 38 byte_stream_new(&bs, 1142);
39
40 snacid = aim_cachesnac(od, 0x0001, 0x0002, 0x0000, NULL, 0);
41 aim_putsnac(&frame->data, 0x0001, 0x0002, 0x0000, snacid);
42 39
43 /* 40 /*
44 * Send only the tool versions that the server cares about (that it 41 * Send only the tool versions that the server cares about (that it
45 * marked as supporting in the server ready SNAC). 42 * marked as supporting in the server ready SNAC).
46 */ 43 */
48 { 45 {
49 aim_module_t *mod; 46 aim_module_t *mod;
50 47
51 if ((mod = aim__findmodulebygroup(od, GPOINTER_TO_UINT(cur->data)))) 48 if ((mod = aim__findmodulebygroup(od, GPOINTER_TO_UINT(cur->data))))
52 { 49 {
53 byte_stream_put16(&frame->data, mod->family); 50 byte_stream_put16(&bs, mod->family);
54 byte_stream_put16(&frame->data, mod->version); 51 byte_stream_put16(&bs, mod->version);
55 byte_stream_put16(&frame->data, mod->toolid); 52 byte_stream_put16(&bs, mod->toolid);
56 byte_stream_put16(&frame->data, mod->toolversion); 53 byte_stream_put16(&bs, mod->toolversion);
57 } 54 }
58 } 55 }
59 56
60 flap_connection_send(conn, frame); 57 snacid = aim_cachesnac(od, 0x0001, 0x0002, 0x0000, NULL, 0);
58 flap_connection_send_snac(od, conn, 0x0001, 0x0002, 0x0000, snacid, &bs);
59
60 byte_stream_destroy(&bs);
61 } 61 }
62 62
63 /* 63 /*
64 * Subtype 0x0003 - Host Online 64 * Subtype 0x0003 - Host Online
65 * 65 *
119 */ 119 */
120 int 120 int
121 aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance) 121 aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance)
122 { 122 {
123 FlapConnection *conn; 123 FlapConnection *conn;
124 FlapFrame *frame; 124 ByteStream bs;
125 aim_snacid_t snacid; 125 aim_snacid_t snacid;
126 GSList *tlvlist = NULL; 126 GSList *tlvlist = NULL;
127 struct chatsnacinfo csi; 127 struct chatsnacinfo csi;
128 128
129 conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS); 129 conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
130 if (!conn || !roomname || !strlen(roomname)) 130 if (!conn || !roomname || !strlen(roomname))
131 return -EINVAL; 131 return -EINVAL;
132 132
133 frame = flap_frame_new(od, 0x02, 512); 133 byte_stream_new(&bs, 502);
134 134
135 memset(&csi, 0, sizeof(csi)); 135 memset(&csi, 0, sizeof(csi));
136 csi.exchange = exchange; 136 csi.exchange = exchange;
137 strncpy(csi.name, roomname, sizeof(csi.name)); 137 strncpy(csi.name, roomname, sizeof(csi.name));
138 csi.instance = instance; 138 csi.instance = instance;
139 139
140 /*
141 * Requesting service chat (0x000e)
142 */
143 byte_stream_put16(&bs, 0x000e);
144
145 aim_tlvlist_add_chatroom(&tlvlist, 0x0001, exchange, roomname, instance);
146 aim_tlvlist_write(&bs, &tlvlist);
147 aim_tlvlist_free(tlvlist);
148
140 snacid = aim_cachesnac(od, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi)); 149 snacid = aim_cachesnac(od, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi));
141 aim_putsnac(&frame->data, 0x0001, 0x0004, 0x0000, snacid); 150 flap_connection_send_snac(od, conn, 0x0001, 0x0004, 0x0000, snacid, &bs);
142 151
143 /* 152 byte_stream_destroy(&bs);
144 * Requesting service chat (0x000e) 153
145 */
146 byte_stream_put16(&frame->data, 0x000e);
147
148 aim_tlvlist_add_chatroom(&tlvlist, 0x0001, exchange, roomname, instance);
149 aim_tlvlist_write(&frame->data, &tlvlist);
150 aim_tlvlist_free(tlvlist);
151
152 flap_connection_send(conn, frame);
153
154 return 0; 154 return 0;
155 } 155 }
156 156
157 /* Subtype 0x0005 - Redirect */ 157 /* Subtype 0x0005 - Redirect */
158 static int 158 static int
374 374
375 /* Subtype 0x0008 - Add Rate Parameter */ 375 /* Subtype 0x0008 - Add Rate Parameter */
376 void 376 void
377 aim_srv_rates_addparam(OscarData *od, FlapConnection *conn) 377 aim_srv_rates_addparam(OscarData *od, FlapConnection *conn)
378 { 378 {
379 FlapFrame *frame; 379 ByteStream bs;
380 aim_snacid_t snacid; 380 aim_snacid_t snacid;
381 GSList *tmp; 381 GSList *tmp;
382 382
383 frame = flap_frame_new(od, 0x02, 512); 383 byte_stream_new(&bs, 502);
384
385 snacid = aim_cachesnac(od, 0x0001, 0x0008, 0x0000, NULL, 0);
386 aim_putsnac(&frame->data, 0x0001, 0x0008, 0x0000, snacid);
387 384
388 for (tmp = conn->rateclasses; tmp != NULL; tmp = tmp->next) 385 for (tmp = conn->rateclasses; tmp != NULL; tmp = tmp->next)
389 { 386 {
390 struct rateclass *rateclass; 387 struct rateclass *rateclass;
391 rateclass = tmp->data; 388 rateclass = tmp->data;
392 byte_stream_put16(&frame->data, rateclass->classid); 389 byte_stream_put16(&bs, rateclass->classid);
393 } 390 }
394 391
395 flap_connection_send(conn, frame); 392 snacid = aim_cachesnac(od, 0x0001, 0x0008, 0x0000, NULL, 0);
393 flap_connection_send_snac(od, conn, 0x0001, 0x0008, 0x0000, snacid, &bs);
394
395 byte_stream_destroy(&bs);
396 } 396 }
397 397
398 /* Subtype 0x0009 - Delete Rate Parameter */ 398 /* Subtype 0x0009 - Delete Rate Parameter */
399 void 399 void
400 aim_srv_rates_delparam(OscarData *od, FlapConnection *conn) 400 aim_srv_rates_delparam(OscarData *od, FlapConnection *conn)
401 { 401 {
402 FlapFrame *frame; 402 ByteStream bs;
403 aim_snacid_t snacid; 403 aim_snacid_t snacid;
404 GSList *tmp; 404 GSList *tmp;
405 405
406 frame = flap_frame_new(od, 0x02, 512); 406 byte_stream_new(&bs, 502);
407
408 snacid = aim_cachesnac(od, 0x0001, 0x0009, 0x0000, NULL, 0);
409 aim_putsnac(&frame->data, 0x0001, 0x0009, 0x0000, snacid);
410 407
411 for (tmp = conn->rateclasses; tmp != NULL; tmp = tmp->next) 408 for (tmp = conn->rateclasses; tmp != NULL; tmp = tmp->next)
412 { 409 {
413 struct rateclass *rateclass; 410 struct rateclass *rateclass;
414 rateclass = tmp->data; 411 rateclass = tmp->data;
415 byte_stream_put16(&frame->data, rateclass->classid); 412 byte_stream_put16(&bs, rateclass->classid);
416 } 413 }
417 414
418 flap_connection_send(conn, frame); 415 snacid = aim_cachesnac(od, 0x0001, 0x0009, 0x0000, NULL, 0);
416 flap_connection_send_snac(od, conn, 0x0001, 0x0009, 0x0000, snacid, &bs);
417
418 byte_stream_destroy(&bs);
419 } 419 }
420 420
421 /* Subtype 0x000a - Rate Change */ 421 /* Subtype 0x000a - Rate Change */
422 static int 422 static int
423 ratechange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) 423 ratechange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
487 * 487 *
488 */ 488 */
489 void 489 void
490 aim_srv_sendpauseack(OscarData *od, FlapConnection *conn) 490 aim_srv_sendpauseack(OscarData *od, FlapConnection *conn)
491 { 491 {
492 FlapFrame *frame; 492 ByteStream bs;
493 aim_snacid_t snacid; 493 aim_snacid_t snacid;
494 GSList *cur; 494 GSList *cur;
495 495
496 frame = flap_frame_new(od, 0x02, 1024); 496 byte_stream_new(&bs, 1014);
497
498 snacid = aim_cachesnac(od, 0x0001, 0x000c, 0x0000, NULL, 0);
499 aim_putsnac(&frame->data, 0x0001, 0x000c, 0x0000, snacid);
500 497
501 /* 498 /*
502 * This list should have all the groups that the original 499 * This list should have all the groups that the original
503 * Host Online / Server Ready said this host supports. And 500 * Host Online / Server Ready said this host supports. And
504 * we want them all back after the migration. 501 * we want them all back after the migration.
505 */ 502 */
506 for (cur = conn->groups; cur != NULL; cur = cur->next) 503 for (cur = conn->groups; cur != NULL; cur = cur->next)
507 byte_stream_put16(&frame->data, GPOINTER_TO_UINT(cur->data)); 504 byte_stream_put16(&bs, GPOINTER_TO_UINT(cur->data));
508 505
509 flap_connection_send(conn, frame); 506 snacid = aim_cachesnac(od, 0x0001, 0x000c, 0x0000, NULL, 0);
507 flap_connection_send_snac(od, conn, 0x0001, 0x000c, 0x0000, snacid, &bs);
508
509 byte_stream_destroy(&bs);
510 } 510 }
511 511
512 /* Subtype 0x000d - Service Resume */ 512 /* Subtype 0x000d - Service Resume */
513 static int 513 static int
514 serverresume(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) 514 serverresume(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
730 * 730 *
731 */ 731 */
732 void 732 void
733 aim_srv_setversions(OscarData *od, FlapConnection *conn) 733 aim_srv_setversions(OscarData *od, FlapConnection *conn)
734 { 734 {
735 FlapFrame *frame; 735 ByteStream bs;
736 aim_snacid_t snacid; 736 aim_snacid_t snacid;
737 GSList *cur; 737 GSList *cur;
738 738
739 frame = flap_frame_new(od, 0x02, 1152); 739 byte_stream_new(&bs, 1142);
740
741 snacid = aim_cachesnac(od, 0x0001, 0x0017, 0x0000, NULL, 0);
742 aim_putsnac(&frame->data, 0x0001, 0x0017, 0x0000, snacid);
743 740
744 /* 741 /*
745 * Send only the versions that the server cares about (that it 742 * Send only the versions that the server cares about (that it
746 * marked as supporting in the server ready SNAC). 743 * marked as supporting in the server ready SNAC).
747 */ 744 */
749 { 746 {
750 aim_module_t *mod; 747 aim_module_t *mod;
751 748
752 if ((mod = aim__findmodulebygroup(od, GPOINTER_TO_UINT(cur->data)))) 749 if ((mod = aim__findmodulebygroup(od, GPOINTER_TO_UINT(cur->data))))
753 { 750 {
754 byte_stream_put16(&frame->data, mod->family); 751 byte_stream_put16(&bs, mod->family);
755 byte_stream_put16(&frame->data, mod->version); 752 byte_stream_put16(&bs, mod->version);
756 } 753 }
757 } 754 }
758 755
759 flap_connection_send(conn, frame); 756 snacid = aim_cachesnac(od, 0x0001, 0x0017, 0x0000, NULL, 0);
757 flap_connection_send_snac(od, conn, 0x0001, 0x0017, 0x0000, snacid, &bs);
758
759 byte_stream_destroy(&bs);
760 } 760 }
761 761
762 /* Subtype 0x0018 - Host versions */ 762 /* Subtype 0x0018 - Host versions */
763 static int 763 static int
764 hostversions(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) 764 hostversions(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
801 aim_srv_setextrainfo(OscarData *od, 801 aim_srv_setextrainfo(OscarData *od,
802 gboolean seticqstatus, guint32 icqstatus, 802 gboolean seticqstatus, guint32 icqstatus,
803 gboolean setavailmsg, const char *availmsg, const char *itmsurl) 803 gboolean setavailmsg, const char *availmsg, const char *itmsurl)
804 { 804 {
805 FlapConnection *conn; 805 FlapConnection *conn;
806 FlapFrame *frame; 806 ByteStream bs;
807 aim_snacid_t snacid; 807 aim_snacid_t snacid;
808 GSList *tlvlist = NULL; 808 GSList *tlvlist = NULL;
809 809
810 if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM))) 810 if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
811 return -EINVAL; 811 return -EINVAL;
851 byte_stream_putstr(&tmpbs, itmsurl); 851 byte_stream_putstr(&tmpbs, itmsurl);
852 byte_stream_put16(&tmpbs, 0x0000); 852 byte_stream_put16(&tmpbs, 0x0000);
853 853
854 aim_tlvlist_add_raw(&tlvlist, 0x001d, 854 aim_tlvlist_add_raw(&tlvlist, 0x001d,
855 byte_stream_curpos(&tmpbs), tmpbs.data); 855 byte_stream_curpos(&tmpbs), tmpbs.data);
856 g_free(tmpbs.data); 856 byte_stream_destroy(&tmpbs);
857 } 857 }
858 858
859 frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(tlvlist)); 859 byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
860
861 aim_tlvlist_write(&bs, &tlvlist);
862 aim_tlvlist_free(tlvlist);
860 863
861 snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0); 864 snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0);
862 aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid); 865 flap_connection_send_snac(od, conn, 0x0001, 0x001e, 0x0000, snacid, &bs);
863 866
864 aim_tlvlist_write(&frame->data, &tlvlist); 867 byte_stream_destroy(&bs);
865 aim_tlvlist_free(tlvlist); 868
866
867 flap_connection_send(conn, frame);
868
869 return 0; 869 return 0;
870 } 870 }
871 871
872 /** 872 /**
873 * Starting this past week (26 Mar 2001, say), AOL has started sending 873 * Starting this past week (26 Mar 2001, say), AOL has started sending
935 935
936 /* Subtype 0x0020 - Client verification reply */ 936 /* Subtype 0x0020 - Client verification reply */
937 int 937 int
938 aim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag) 938 aim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag)
939 { 939 {
940 FlapFrame *frame; 940 ByteStream bs;
941 aim_snacid_t snacid; 941 aim_snacid_t snacid;
942 942
943 if (!od || !conn) 943 if (!od || !conn)
944 return -EINVAL; 944 return -EINVAL;
945 945
946 frame = flap_frame_new(od, 0x02, 10+2+16); 946 byte_stream_new(&bs, 2+16);
947 947
948 snacid = aim_cachesnac(od, 0x0001, 0x0020, 0x0000, NULL, 0); 948 byte_stream_put16(&bs, 0x0010); /* md5 is always 16 bytes */
949
950 aim_putsnac(&frame->data, 0x0001, 0x0020, 0x0000, snacid);
951 byte_stream_put16(&frame->data, 0x0010); /* md5 is always 16 bytes */
952 949
953 if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */ 950 if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */
954 951
955 byte_stream_putraw(&frame->data, buf, 0x10); 952 byte_stream_putraw(&bs, buf, 0x10);
956 953
957 } else if (buf && (len > 0)) { /* use input buffer */ 954 } else if (buf && (len > 0)) { /* use input buffer */
958 PurpleCipher *cipher; 955 PurpleCipher *cipher;
959 PurpleCipherContext *context; 956 PurpleCipherContext *context;
960 guchar digest[16]; 957 guchar digest[16];
964 context = purple_cipher_context_new(cipher, NULL); 961 context = purple_cipher_context_new(cipher, NULL);
965 purple_cipher_context_append(context, buf, len); 962 purple_cipher_context_append(context, buf, len);
966 purple_cipher_context_digest(context, 16, digest, NULL); 963 purple_cipher_context_digest(context, 16, digest, NULL);
967 purple_cipher_context_destroy(context); 964 purple_cipher_context_destroy(context);
968 965
969 byte_stream_putraw(&frame->data, digest, 0x10); 966 byte_stream_putraw(&bs, digest, 0x10);
970 967
971 } else if (len == 0) { /* no length, just hash NULL (buf is optional) */ 968 } else if (len == 0) { /* no length, just hash NULL (buf is optional) */
972 PurpleCipher *cipher; 969 PurpleCipher *cipher;
973 PurpleCipherContext *context; 970 PurpleCipherContext *context;
974 guchar digest[16]; 971 guchar digest[16];
983 context = purple_cipher_context_new(cipher, NULL); 980 context = purple_cipher_context_new(cipher, NULL);
984 purple_cipher_context_append(context, &nil, 0); 981 purple_cipher_context_append(context, &nil, 0);
985 purple_cipher_context_digest(context, 16, digest, NULL); 982 purple_cipher_context_digest(context, 16, digest, NULL);
986 purple_cipher_context_destroy(context); 983 purple_cipher_context_destroy(context);
987 984
988 byte_stream_putraw(&frame->data, digest, 0x10); 985 byte_stream_putraw(&bs, digest, 0x10);
989 986
990 } else { 987 } else {
991 988
992 /* 989 /*
993 * This data is correct for AIM 3.5.1670. 990 * This data is correct for AIM 3.5.1670.
997 * 994 *
998 */ 995 */
999 if ((offset == 0x03ffffff) && (len == 0x03ffffff)) { 996 if ((offset == 0x03ffffff) && (len == 0x03ffffff)) {
1000 997
1001 #if 1 /* with "AnrbnrAqhfzcd" */ 998 #if 1 /* with "AnrbnrAqhfzcd" */
1002 byte_stream_put32(&frame->data, 0x44a95d26); 999 byte_stream_put32(&bs, 0x44a95d26);
1003 byte_stream_put32(&frame->data, 0xd2490423); 1000 byte_stream_put32(&bs, 0xd2490423);
1004 byte_stream_put32(&frame->data, 0x93b8821f); 1001 byte_stream_put32(&bs, 0x93b8821f);
1005 byte_stream_put32(&frame->data, 0x51c54b01); 1002 byte_stream_put32(&bs, 0x51c54b01);
1006 #else /* no filename */ 1003 #else /* no filename */
1007 byte_stream_put32(&frame->data, 0x1df8cbae); 1004 byte_stream_put32(&bs, 0x1df8cbae);
1008 byte_stream_put32(&frame->data, 0x5523b839); 1005 byte_stream_put32(&bs, 0x5523b839);
1009 byte_stream_put32(&frame->data, 0xa0e10db3); 1006 byte_stream_put32(&bs, 0xa0e10db3);
1010 byte_stream_put32(&frame->data, 0xa46d3b39); 1007 byte_stream_put32(&bs, 0xa46d3b39);
1011 #endif 1008 #endif
1012 1009
1013 } else 1010 } else
1014 purple_debug_warning("oscar", "sendmemblock: unknown hash request\n"); 1011 purple_debug_warning("oscar", "sendmemblock: unknown hash request\n");
1015 1012
1016 } 1013 }
1017 1014
1018 flap_connection_send(conn, frame); 1015 snacid = aim_cachesnac(od, 0x0001, 0x0020, 0x0000, NULL, 0);
1019 1016 flap_connection_send_snac(od, conn, 0x0001, 0x0020, 0x0000, snacid, &bs);
1017
1018 byte_stream_destroy(&bs);
1019
1020 return 0; 1020 return 0;
1021 } 1021 }
1022 1022
1023 /* 1023 /*
1024 * Subtype 0x0021 - Receive our extended status 1024 * Subtype 0x0021 - Receive our extended status