| 755 /* TODO: Free copy cloned from msim_preprocess_incoming(). */ |
755 /* TODO: Free copy cloned from msim_preprocess_incoming(). */ |
| 756 //XXX msim_msg_free(msg); |
756 //XXX msim_msg_free(msg); |
| 757 g_hash_table_destroy(body); |
757 g_hash_table_destroy(body); |
| 758 } |
758 } |
| 759 |
759 |
| |
760 /* Lookup a username by userid, from buddy list. |
| |
761 * |
| |
762 * @param wanted_uid |
| |
763 * |
| |
764 * @return Username of wanted_uid, if on blist, or NULL. Static string. |
| |
765 * |
| |
766 * XXX WARNING: UNKNOWN MEMORY CORRUPTION HERE! |
| |
767 */ |
| |
768 static const gchar *msim_uid2username_from_blist(MsimSession *session, guint wanted_uid) |
| |
769 { |
| |
770 GSList *buddies, *buddies_head; |
| |
771 |
| |
772 for (buddies = buddies_head = purple_find_buddies(session->account, NULL); |
| |
773 buddies; |
| |
774 buddies = g_slist_next(buddies)) |
| |
775 { |
| |
776 PurpleBuddy *buddy; |
| |
777 guint uid; |
| |
778 gchar *name; |
| |
779 |
| |
780 buddy = buddies->data; |
| |
781 |
| |
782 uid = purple_blist_node_get_int(&buddy->node, "uid"); |
| |
783 |
| |
784 /* name = buddy->name; */ /* crash */ |
| |
785 /* name = PURPLE_BLIST_NODE_NAME(&buddy->node); */ /* crash */ |
| |
786 |
| |
787 /* XXX Is this right? Memory corruption here somehow. Happens only |
| |
788 * when return one of these values. */ |
| |
789 name = purple_buddy_get_name(buddy); /* crash */ |
| |
790 /* return name; */ /* crash (with above) */ |
| |
791 |
| |
792 /* name = NULL; */ /* no crash */ |
| |
793 /* return NULL; */ /* no crash (with anything) */ |
| |
794 |
| |
795 /* crash = |
| |
796 *** glibc detected *** pidgin: realloc(): invalid pointer: 0x0000000000d2aec0 *** |
| |
797 ======= Backtrace: ========= |
| |
798 /lib/libc.so.6(__libc_realloc+0x323)[0x2b7bfc012e03] |
| |
799 /usr/lib/libglib-2.0.so.0(g_realloc+0x31)[0x2b7bfba79a41] |
| |
800 /usr/lib/libgtk-x11-2.0.so.0(gtk_tree_path_append_index+0x3a)[0x2b7bfa110d5a] |
| |
801 /usr/lib/libgtk-x11-2.0.so.0[0x2b7bfa1287dc] |
| |
802 /usr/lib/libgtk-x11-2.0.so.0[0x2b7bfa128e56] |
| |
803 /usr/lib/libgtk-x11-2.0.so.0[0x2b7bfa128efd] |
| |
804 /usr/lib/libglib-2.0.so.0(g_main_context_dispatch+0x1b4)[0x2b7bfba72c84] |
| |
805 /usr/lib/libglib-2.0.so.0[0x2b7bfba75acd] |
| |
806 /usr/lib/libglib-2.0.so.0(g_main_loop_run+0x1ca)[0x2b7bfba75dda] |
| |
807 /usr/lib/libgtk-x11-2.0.so.0(gtk_main+0xa3)[0x2b7bfa0475f3] |
| |
808 pidgin(main+0x8be)[0x46b45e] |
| |
809 /lib/libc.so.6(__libc_start_main+0xf4)[0x2b7bfbfbf0c4] |
| |
810 pidgin(gtk_widget_grab_focus+0x39)[0x429ab9] |
| |
811 |
| |
812 or: |
| |
813 *** glibc detected *** /usr/local/bin/pidgin: malloc(): memory corruption (fast): 0x0000000000c10076 *** |
| |
814 (gdb) bt |
| |
815 #0 0x00002b4074ecd47b in raise () from /lib/libc.so.6 |
| |
816 #1 0x00002b4074eceda0 in abort () from /lib/libc.so.6 |
| |
817 #2 0x00002b4074f0453b in __fsetlocking () from /lib/libc.so.6 |
| |
818 #3 0x00002b4074f0c810 in free () from /lib/libc.so.6 |
| |
819 #4 0x00002b4074f0d6dd in malloc () from /lib/libc.so.6 |
| |
820 #5 0x00002b4074974b5b in g_malloc () from /usr/lib/libglib-2.0.so.0 |
| |
821 #6 0x00002b40749868bf in g_strdup () from /usr/lib/libglib-2.0.so.0 |
| |
822 #7 0x00002b407810969f in msim_parse ( |
| |
823 raw=0xd2a910 "\\bm\\100\\f\\3656574\\msg\\|s|0|ss|Offline") |
| |
824 at message.c:648 |
| |
825 #8 0x00002b407810889c in msim_input_cb (gc_uncasted=0xcf92c0, |
| |
826 source=<value optimized out>, cond=<value optimized out>) at myspace.c:1478 |
| |
827 |
| |
828 |
| |
829 Why is it crashing in msim_parse()'s g_strdup()? |
| |
830 */ |
| |
831 |
| |
832 |
| |
833 purple_debug_info("msim", "msim_uid2username_from_blist: %s's uid=%d (want %d)\n", |
| |
834 name, uid, wanted_uid); |
| |
835 |
| |
836 if (uid == wanted_uid) |
| |
837 { |
| |
838 g_slist_free(buddies_head); |
| |
839 |
| |
840 return name; |
| |
841 } |
| |
842 } |
| |
843 |
| |
844 g_slist_free(buddies_head); |
| |
845 return NULL; |
| |
846 } |
| |
847 |
| 760 /** Preprocess incoming messages, resolving as needed, calling msim_process() when ready to process. |
848 /** Preprocess incoming messages, resolving as needed, calling msim_process() when ready to process. |
| 761 * |
849 * |
| 762 * TODO: if no uid to resolve, process immediately. if uid, check if know username, |
850 * TODO: if no uid to resolve, process immediately. if uid, check if know username, |
| 763 * if so, tag and process immediately, if not, queue, send resolve msg, and process |
851 * if so, tag and process immediately, if not, queue, send resolve msg, and process |
| 764 * once get username. |
852 * once get username. |
| 768 */ |
856 */ |
| 769 gboolean msim_preprocess_incoming(MsimSession *session, MsimMessage *msg) |
857 gboolean msim_preprocess_incoming(MsimSession *session, MsimMessage *msg) |
| 770 { |
858 { |
| 771 if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) |
859 if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) |
| 772 { |
860 { |
| |
861 guint uid; |
| |
862 const gchar *username; |
| |
863 |
| 773 /* 'f' = userid message is from, in buddy messages */ |
864 /* 'f' = userid message is from, in buddy messages */ |
| 774 |
865 uid = msim_msg_get_integer(msg, "f"); |
| 775 /* TODO XXX IMPORTANT TODO: if know uid->username mapping already, process immediately */ |
866 |
| 776 /* TODO XXX Currently, uid is ALWAYS explicitly resolved, on each message, by sending |
867 /* TODO: Make caching work. Currently it is commented out because |
| 777 * a getuserbyuserid message. This is very wasteful. TODO: Be frugal. |
868 * it crashes for unknown reasons, memory realloc error. */ |
| 778 */ |
869 //#define _MSIM_UID2USERNAME_WORKS |
| 779 |
870 #ifdef _MSIM_UID2USERNAME_WORKS |
| 780 /* Send lookup request. */ |
871 username = msim_uid2username_from_blist(session, uid); |
| 781 /* XXX: where is msim_msg_get_string() freed? make _strdup and _nonstrdup. */ |
872 #else |
| 782 purple_debug_info("msim", "msim_incoming: sending lookup, setting up callback\n"); |
873 username = NULL; |
| 783 msim_lookup_user(session, msim_msg_get_string(msg, "f"), msim_incoming_resolved, msim_msg_clone(msg)); |
874 #endif |
| 784 |
875 |
| 785 /* indeterminate */ |
876 if (username) |
| 786 return TRUE; |
877 { |
| |
878 /* Know username already, use it. */ |
| |
879 purple_debug_info("msim", "msim_preprocess_incoming: tagging with _username=%s\n", |
| |
880 username); |
| |
881 msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username)); |
| |
882 return msim_process(session, msg); |
| |
883 |
| |
884 } else { |
| |
885 /* Send lookup request. */ |
| |
886 /* XXX: where is msim_msg_get_string() freed? make _strdup and _nonstrdup. */ |
| |
887 purple_debug_info("msim", "msim_incoming: sending lookup, setting up callback\n"); |
| |
888 msim_lookup_user(session, msim_msg_get_string(msg, "f"), msim_incoming_resolved, msim_msg_clone(msg)); |
| |
889 |
| |
890 /* indeterminate */ |
| |
891 return TRUE; |
| |
892 } |
| 787 } else { |
893 } else { |
| 788 /* Nothing to resolve - send directly to processing. */ |
894 /* Nothing to resolve - send directly to processing. */ |
| 789 return msim_process(session, msg); |
895 return msim_process(session, msg); |
| 790 } |
896 } |
| 791 } |
897 } |
| 896 |
1002 |
| 897 /* TODO: implement a better hash-like interface, and use it. */ |
1003 /* TODO: implement a better hash-like interface, and use it. */ |
| 898 username = g_hash_table_lookup(body, "UserName"); |
1004 username = g_hash_table_lookup(body, "UserName"); |
| 899 if (username) |
1005 if (username) |
| 900 { |
1006 { |
| 901 /* TODO: permanently associated with blist item, if in buddy in blist, |
1007 PurpleBuddy *buddy; |
| 902 * See purple_blist_node_set_int(). */ |
1008 gchar *uid; |
| 903 g_hash_table_insert(session->user_lookup_cache, g_strdup(username), body); |
1009 |
| |
1010 uid = g_hash_table_lookup(body, "UserID"); |
| |
1011 g_assert(uid); |
| |
1012 |
| |
1013 /* Associate uid with user on buddy list. This is saved to blist.xml. */ |
| |
1014 |
| |
1015 purple_debug_info("msim", "associating %d with %s\n", uid, username); |
| |
1016 |
| |
1017 buddy = purple_find_buddy(session->account, username); |
| |
1018 if (buddy) |
| |
1019 { |
| |
1020 purple_blist_node_set_int(&buddy->node, "uid", atoi(uid)); |
| |
1021 } |
| 904 } else { |
1022 } else { |
| 905 purple_debug_info("msim", |
1023 purple_debug_info("msim", |
| 906 "msim_process_reply: not caching body, no UserName\n"); |
1024 "msim_process_reply: not caching body, no UserName\n"); |
| 907 } |
1025 } |
| 908 |
1026 |
| 1455 |
1573 |
| 1456 session->magic = MSIM_SESSION_STRUCT_MAGIC; |
1574 session->magic = MSIM_SESSION_STRUCT_MAGIC; |
| 1457 session->account = acct; |
1575 session->account = acct; |
| 1458 session->gc = purple_account_get_connection(acct); |
1576 session->gc = purple_account_get_connection(acct); |
| 1459 session->fd = -1; |
1577 session->fd = -1; |
| |
1578 |
| |
1579 /* TODO: Remove. */ |
| 1460 session->user_lookup_cb = g_hash_table_new_full(g_direct_hash, |
1580 session->user_lookup_cb = g_hash_table_new_full(g_direct_hash, |
| 1461 g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */ |
1581 g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */ |
| 1462 session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash, |
1582 session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash, |
| 1463 g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are, |
1583 g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are, |
| 1464 they could be integers inside gpointers |
1584 they could be integers inside gpointers |
| 1465 or strings, so I don't freed them. |
1585 or strings, so I don't freed them. |
| 1466 Figure this out, once free cache. */ |
1586 Figure this out, once free cache. */ |
| 1467 session->user_lookup_cache = g_hash_table_new_full(g_str_hash, g_str_equal, |
1587 session->user_lookup_cache = g_hash_table_new_full(g_str_hash, g_str_equal, |
| 1468 g_free, (GDestroyNotify)g_hash_table_destroy); |
1588 g_free, (GDestroyNotify)g_hash_table_destroy); |
| |
1589 |
| 1469 session->rxoff = 0; |
1590 session->rxoff = 0; |
| 1470 session->rxbuf = g_new0(gchar, MSIM_READ_BUF_SIZE); |
1591 session->rxbuf = g_new0(gchar, MSIM_READ_BUF_SIZE); |
| 1471 session->next_rid = 1; |
1592 session->next_rid = 1; |
| 1472 |
1593 |
| 1473 return session; |
1594 return session; |