comparison libpurple/protocols/bonjour/jabber.c @ 21667:919338d399ae

merge of '2fcb5d2cb35c5ba692592e22bc442c3d62000f85' and '61c8d242483046a3b3b43cd1afbb794af35a08c9'
author Ethan Blanton <elb@pidgin.im>
date Tue, 27 Nov 2007 15:57:08 +0000
parents 4fe9acb6b514 9736ee1ca29e
children fded60f269bc
comparison
equal deleted inserted replaced
21438:4fe9acb6b514 21667:919338d399ae
89 return "12"; 89 return "12";
90 } 90 }
91 #endif 91 #endif
92 92
93 static BonjourJabberConversation * 93 static BonjourJabberConversation *
94 bonjour_jabber_conv_new() { 94 bonjour_jabber_conv_new(PurpleBuddy *pb) {
95 95
96 BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1); 96 BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1);
97 bconv->socket = -1; 97 bconv->socket = -1;
98 bconv->tx_buf = purple_circ_buffer_new(512); 98 bconv->tx_buf = purple_circ_buffer_new(512);
99 bconv->tx_handler = 0; 99 bconv->tx_handler = 0;
100 bconv->rx_handler = 0; 100 bconv->rx_handler = 0;
101 bconv->pb = pb;
101 102
102 return bconv; 103 return bconv;
103 } 104 }
104 105
105 106
326 327
327 return ret; 328 return ret;
328 } 329 }
329 330
330 void bonjour_jabber_process_packet(PurpleBuddy *pb, xmlnode *packet) { 331 void bonjour_jabber_process_packet(PurpleBuddy *pb, xmlnode *packet) {
332
333 g_return_if_fail(packet != NULL);
334
331 if (!strcmp(packet->name, "message")) 335 if (!strcmp(packet->name, "message"))
332 _jabber_parse_and_write_message_to_ui(packet, pb); 336 _jabber_parse_and_write_message_to_ui(packet, pb);
333 else if(!strcmp(packet->name, "iq")) 337 else if(!strcmp(packet->name, "iq"))
334 xep_iq_parse(packet, NULL, pb); 338 xep_iq_parse(packet, NULL, pb);
335 else 339 else
336 purple_debug_warning("bonjour", "Unknown packet: %s\n", 340 purple_debug_warning("bonjour", "Unknown packet: %s\n", packet->name ? packet->name : "(null)");
337 packet->name);
338 } 341 }
339 342
340 343
341 static void 344 static void
342 _client_socket_handler(gpointer data, gint socket, PurpleInputCondition condition) 345 _client_socket_handler(gpointer data, gint socket, PurpleInputCondition condition)
350 /* Read the data from the socket */ 353 /* Read the data from the socket */
351 if ((len = recv(socket, message, sizeof(message) - 1, 0)) == -1) { 354 if ((len = recv(socket, message, sizeof(message) - 1, 0)) == -1) {
352 /* There have been an error reading from the socket */ 355 /* There have been an error reading from the socket */
353 if (errno != EAGAIN) { 356 if (errno != EAGAIN) {
354 BonjourBuddy *bb = pb->proto_data; 357 BonjourBuddy *bb = pb->proto_data;
355 358 const char *err = g_strerror(errno);
356 purple_debug_warning("bonjour", "receive error: %s\n", g_strerror(errno)); 359
360 purple_debug_warning("bonjour", "receive error: %s\n", err ? err : "(null)");
357 361
358 bonjour_jabber_close_conversation(bb->conversation); 362 bonjour_jabber_close_conversation(bb->conversation);
359 bb->conversation = NULL; 363 bb->conversation = NULL;
360 364
361 /* I guess we really don't need to notify the user. 365 /* I guess we really don't need to notify the user.
362 * If they try to send another message it'll reconnect */ 366 * If they try to send another message it'll reconnect */
363 } 367 }
364 return; 368 return;
365 } else if (len == 0) { /* The other end has closed the socket */ 369 } else if (len == 0) { /* The other end has closed the socket */
366 purple_debug_warning("bonjour", "Connection closed (without stream end) by %s.\n", pb->name); 370 purple_debug_warning("bonjour", "Connection closed (without stream end) by %s.\n", pb->name ? pb->name : "(null)");
367 bonjour_jabber_stream_ended(pb); 371 bonjour_jabber_stream_ended(pb);
368 return; 372 return;
369 } else { 373 } else {
370 message_length = len; 374 message_length = len;
371 message[message_length] = '\0'; 375 message[message_length] = '\0';
401 #endif 405 #endif
402 /* Close the socket, clear the watcher and free memory */ 406 /* Close the socket, clear the watcher and free memory */
403 bonjour_jabber_close_conversation(bb->conversation); 407 bonjour_jabber_close_conversation(bb->conversation);
404 bb->conversation = NULL; 408 bb->conversation = NULL;
405 } 409 }
406
407 } 410 }
408 411
409 void bonjour_jabber_stream_started(PurpleBuddy *pb) { 412 void bonjour_jabber_stream_started(PurpleBuddy *pb) {
410 BonjourBuddy *bb = pb->proto_data; 413 BonjourBuddy *bb = pb->proto_data;
411 BonjourJabberConversation *bconv = bb->conversation; 414 BonjourJabberConversation *bconv = bb->conversation;
573 bb = pb->proto_data; 576 bb = pb->proto_data;
574 577
575 /* Check if the conversation has been previously started */ 578 /* Check if the conversation has been previously started */
576 if (bb->conversation == NULL) 579 if (bb->conversation == NULL)
577 { 580 {
578 bb->conversation = bonjour_jabber_conv_new(); 581 bb->conversation = bonjour_jabber_conv_new(pb);
579 582
580 if (!bonjour_jabber_stream_init(pb, client_socket)) { 583 if (!bonjour_jabber_stream_init(pb, client_socket)) {
581 close(client_socket); 584 close(client_socket);
582 return; 585 return;
583 } 586 }
711 bb->conversation = NULL; 714 bb->conversation = NULL;
712 return; 715 return;
713 } 716 }
714 } 717 }
715 718
716 int 719 static PurpleBuddy *
717 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body) 720 _find_or_start_conversation(BonjourJabber *data, const gchar *to)
718 { 721 {
719 xmlnode *message_node, *node, *node2; 722 PurpleBuddy *pb = NULL;
720 gchar *message; 723 BonjourBuddy *bb = NULL;
721 PurpleBuddy *pb; 724
722 BonjourBuddy *bb; 725 g_return_val_if_fail(data != NULL, NULL);
723 int ret; 726 g_return_val_if_fail(to != NULL, NULL);
724 727
725 pb = purple_find_buddy(data->account, to); 728 pb = purple_find_buddy(data->account, to);
726 if (pb == NULL) { 729 if (pb == NULL || pb->proto_data == NULL)
727 purple_debug_info("bonjour", "Can't send a message to an offline buddy (%s).\n", to);
728 /* You can not send a message to an offline buddy */ 730 /* You can not send a message to an offline buddy */
729 return -10000; 731 return NULL;
730 } 732
731 733 bb = (BonjourBuddy *) pb->proto_data;
732 bb = pb->proto_data;
733 734
734 /* Check if there is a previously open conversation */ 735 /* Check if there is a previously open conversation */
735 if (bb->conversation == NULL) 736 if (bb->conversation == NULL)
736 { 737 {
737 PurpleProxyConnectData *connect_data; 738 PurpleProxyConnectData *connect_data;
738 PurpleProxyInfo *proxy_info; 739 PurpleProxyInfo *proxy_info;
740
741 purple_debug_info("bonjour", "Starting conversation with %s\n", to);
739 742
740 /* Make sure that the account always has a proxy of "none". 743 /* Make sure that the account always has a proxy of "none".
741 * This is kind of dirty, but proxy_connect_none() isn't exposed. */ 744 * This is kind of dirty, but proxy_connect_none() isn't exposed. */
742 proxy_info = purple_account_get_proxy_info(data->account); 745 proxy_info = purple_account_get_proxy_info(data->account);
743 if (proxy_info == NULL) { 746 if (proxy_info == NULL) {
744 proxy_info = purple_proxy_info_new(); 747 proxy_info = purple_proxy_info_new();
745 purple_account_set_proxy_info(data->account, proxy_info); 748 purple_account_set_proxy_info(data->account, proxy_info);
746 } 749 }
747 purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE); 750 purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE);
748 751
749 connect_data = 752 connect_data = purple_proxy_connect(data->account->gc, data->account,
750 purple_proxy_connect(data->account->gc, data->account, bb->ip, 753 bb->ip, bb->port_p2pj, _connected_to_buddy, pb);
751 bb->port_p2pj, _connected_to_buddy, pb);
752 754
753 if (connect_data == NULL) { 755 if (connect_data == NULL) {
754 purple_debug_error("bonjour", "Unable to connect to buddy (%s).\n", to); 756 purple_debug_error("bonjour", "Unable to connect to buddy (%s).\n", to);
755 return -10001; 757 return NULL;
756 } 758 }
757 759
758 bb->conversation = bonjour_jabber_conv_new(); 760 bb->conversation = bonjour_jabber_conv_new(pb);
759 bb->conversation->connect_data = connect_data; 761 bb->conversation->connect_data = connect_data;
760 /* We don't want _send_data() to register the tx_handler; 762 /* We don't want _send_data() to register the tx_handler;
761 * that neeeds to wait until we're actually connected. */ 763 * that neeeds to wait until we're actually connected. */
762 bb->conversation->tx_handler = 0; 764 bb->conversation->tx_handler = 0;
763 } 765 }
766 return pb;
767 }
768
769 int
770 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body)
771 {
772 xmlnode *message_node, *node, *node2;
773 gchar *message;
774 PurpleBuddy *pb;
775 BonjourBuddy *bb;
776 int ret;
777
778 pb = _find_or_start_conversation(data, to);
779 if (pb == NULL) {
780 purple_debug_info("bonjour", "Can't send a message to an offline buddy (%s).\n", to);
781 /* You can not send a message to an offline buddy */
782 return -10000;
783 }
784
785 bb = pb->proto_data;
764 786
765 message_node = xmlnode_new("message"); 787 message_node = xmlnode_new("message");
766 xmlnode_set_attrib(message_node, "to", bb->name); 788 xmlnode_set_attrib(message_node, "to", bb->name);
767 xmlnode_set_attrib(message_node, "from", purple_account_get_username(data->account)); 789 xmlnode_set_attrib(message_node, "from", purple_account_get_username(data->account));
768 xmlnode_set_attrib(message_node, "type", "chat"); 790 xmlnode_set_attrib(message_node, "type", "chat");
797 } 819 }
798 820
799 void 821 void
800 bonjour_jabber_close_conversation(BonjourJabberConversation *bconv) 822 bonjour_jabber_close_conversation(BonjourJabberConversation *bconv)
801 { 823 {
802 if (bconv != NULL) 824 if (bconv != NULL) {
803 { 825 GList *xfers, *tmp_next;
826 BonjourData *bd = bconv->pb->account->gc->proto_data;
827
828 /* Cancel any file transfers that are waiting to begin */
829 xfers = bd->xfer_lists;
830 while(xfers != NULL) {
831 PurpleXfer *xfer = xfers->data;
832 tmp_next = xfers->next;
833 /* We only need to cancel this if it hasn't actually started transferring. */
834 /* This will change if we ever support IBB transfers. */
835 if (strcmp(xfer->who, bconv->pb->name) == 0
836 && (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_NOT_STARTED
837 || purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_UNKNOWN)) {
838 purple_xfer_cancel_remote(xfer);
839 }
840 xfers = tmp_next;
841 }
842
804 /* Close the socket and remove the watcher */ 843 /* Close the socket and remove the watcher */
805 if (bconv->socket >= 0) { 844 if (bconv->socket >= 0) {
806 /* Send the end of the stream to the other end of the conversation */ 845 /* Send the end of the stream to the other end of the conversation */
807 if (bconv->sent_stream_start) 846 if (bconv->sent_stream_start)
808 send(bconv->socket, STREAM_END, strlen(STREAM_END), 0); 847 send(bconv->socket, STREAM_END, strlen(STREAM_END), 0);
853 } 892 }
854 893
855 g_slist_free(buddies); 894 g_slist_free(buddies);
856 } 895 }
857 } 896 }
858 static PurpleBuddy *
859 _start_conversation(BonjourJabber *data, const gchar *to)
860 {
861 PurpleBuddy *pb = NULL;
862 BonjourBuddy *bb = NULL;
863
864 if(data == NULL || to == NULL)
865 return NULL;
866
867 purple_debug_info("Bonjour", "start-conversation with %s - \n", to);
868
869 pb = purple_find_buddy(data->account, to);
870 if (pb == NULL)
871 /* You can not send a message to an offline buddy */
872 return NULL;
873
874 bb = (BonjourBuddy *) pb->proto_data;
875 if(bb == NULL)
876 return NULL;
877
878 /* Check if there is a previously open conversation */
879 if (bb->conversation == NULL)
880 {
881 PurpleProxyConnectData *connect_data;
882 PurpleProxyInfo *proxy_info;
883
884 /* Make sure that the account always has a proxy of "none".
885 * This is kind of dirty, but proxy_connect_none() isn't exposed. */
886 proxy_info = purple_account_get_proxy_info(data->account);
887 if (proxy_info == NULL) {
888 proxy_info = purple_proxy_info_new();
889 purple_account_set_proxy_info(data->account, proxy_info);
890 }
891 purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE);
892
893 connect_data = purple_proxy_connect(data->account->gc, data->account,
894 bb->ip, bb->port_p2pj, _connected_to_buddy, pb);
895
896 if (connect_data == NULL) {
897 purple_debug_error("bonjour", "Unable to connect to buddy (%s).\n", to);
898 return NULL;
899 }
900
901 bb->conversation = bonjour_jabber_conv_new();
902 bb->conversation->connect_data = connect_data;
903 /* We don't want _send_data() to register the tx_handler;
904 * that neeeds to wait until we're actually connected. */
905 bb->conversation->tx_handler = 0;
906 }
907 return pb;
908 }
909 897
910 XepIq * 898 XepIq *
911 xep_iq_new(void *data, XepIqType type, const gchar *to, const gchar *id) 899 xep_iq_new(void *data, XepIqType type, const char *to, const char *from, const char *id)
912 { 900 {
913 xmlnode *iq_node = NULL; 901 xmlnode *iq_node = NULL;
914 XepIq *iq = NULL; 902 XepIq *iq = NULL;
915 903
916 if(data == NULL || to == NULL || id == NULL) 904 g_return_val_if_fail(data != NULL, NULL);
917 return NULL; 905 g_return_val_if_fail(to != NULL, NULL);
918 iq = g_new0(XepIq, 1); 906 g_return_val_if_fail(id != NULL, NULL);
919 if(iq == NULL)
920 return NULL;
921 907
922 iq_node = xmlnode_new("iq"); 908 iq_node = xmlnode_new("iq");
923 if(iq_node == NULL) {
924 g_free(iq);
925 return NULL;
926 }
927 909
928 xmlnode_set_attrib(iq_node, "to", to); 910 xmlnode_set_attrib(iq_node, "to", to);
911 xmlnode_set_attrib(iq_node, "from", from);
929 xmlnode_set_attrib(iq_node, "id", id); 912 xmlnode_set_attrib(iq_node, "id", id);
930 switch (type) { 913 switch (type) {
931 case XEP_IQ_SET: 914 case XEP_IQ_SET:
932 xmlnode_set_attrib(iq_node, "type", "set"); 915 xmlnode_set_attrib(iq_node, "type", "set");
933 break; 916 break;
944 default: 927 default:
945 xmlnode_set_attrib(iq_node, "type", "none"); 928 xmlnode_set_attrib(iq_node, "type", "none");
946 break; 929 break;
947 } 930 }
948 931
932 iq = g_new0(XepIq, 1);
949 iq->node = iq_node; 933 iq->node = iq_node;
950 iq->type = type; 934 iq->type = type;
951 iq->data = ((BonjourData*)data)->jabber_data; 935 iq->data = ((BonjourData*)data)->jabber_data;
952 iq->to = (char*)to; 936 iq->to = (char*)to;
937
953 return iq; 938 return iq;
954 } 939 }
955 940
956 static gboolean 941 static gboolean
957 check_if_blocked(PurpleBuddy *pb) 942 check_if_blocked(PurpleBuddy *pb)
965 950
966 acc = pb->account; 951 acc = pb->account;
967 952
968 for(l = acc->deny; l != NULL; l = l->next) { 953 for(l = acc->deny; l != NULL; l = l->next) {
969 if(!purple_utf8_strcasecmp(pb->name, (char *)l->data)) { 954 if(!purple_utf8_strcasecmp(pb->name, (char *)l->data)) {
970 purple_debug_info("Bonjour", "%s has been blocked.\n", pb->name, acc->username); 955 purple_debug_info("bonjour", "%s has been blocked.\n", pb->name, acc->username);
971 blocked = TRUE; 956 blocked = TRUE;
972 break; 957 break;
973 } 958 }
974 } 959 }
975 return blocked; 960 return blocked;
989 } 974 }
990 975
991 if(check_if_blocked(pb)) 976 if(check_if_blocked(pb))
992 return; 977 return;
993 978
994 if ((child = xmlnode_get_child(packet, "si")) || (child = xmlnode_get_child(packet, "si"))) 979 if ((child = xmlnode_get_child(packet, "si")) || (child = xmlnode_get_child(packet, "error")))
995 xep_si_parse(connection, packet, pb); 980 xep_si_parse(connection, packet, pb);
996 else 981 else
997 xep_bytestreams_parse(connection, packet, pb); 982 xep_bytestreams_parse(connection, packet, pb);
998 } 983 }
999 984
1000 int 985 int
1001 xep_iq_send(XepIq *iq) 986 xep_iq_send_and_free(XepIq *iq)
1002 { 987 {
1003 char *msg = NULL;
1004 gint msg_len = 0;
1005 int ret = -1; 988 int ret = -1;
1006 PurpleBuddy *pb = NULL; 989 PurpleBuddy *pb = NULL;
1007 /* Convert xml node into stream */ 990
1008 msg = xmlnode_to_str(iq->node, &msg_len); 991 /* start the talk, reuse the message socket */
992 pb = _find_or_start_conversation ((BonjourJabber*)iq->data, iq->to);
993 /* Send the message */
994 if (pb != NULL) {
995 /* Convert xml node into stream */
996 gchar *msg = xmlnode_to_str(iq->node, NULL);
997 ret = _send_data(pb, msg);
998 g_free(msg);
999 }
1000
1009 xmlnode_free(iq->node); 1001 xmlnode_free(iq->node);
1010 /* start the talk, reuse the message socket */ 1002 iq->node = NULL;
1011 pb = _start_conversation ((BonjourJabber*)iq->data, iq->to); 1003 g_free(iq);
1012 /* Send the message */ 1004
1013 if (pb != NULL) 1005 return (ret >= 0) ? 0 : -1;
1014 ret = _send_data(pb, msg); 1006 }
1015 g_free(msg); 1007
1016 if (ret == -1) 1008 /* This returns a ';' delimited string containing all non-localhost IPs */
1017 return -1; 1009 const char *
1018 return 0;
1019 }
1020
1021 char *
1022 purple_network_get_my_ip_ext2(int fd) 1010 purple_network_get_my_ip_ext2(int fd)
1023 { 1011 {
1024 char buffer[1024]; 1012 char buffer[1024];
1025 static char ip_ext[17 * 10]; 1013 static char ip_ext[17 * 10];
1026 char *tmp; 1014 char *tmp;
1029 struct ifreq *ifr; 1017 struct ifreq *ifr;
1030 struct sockaddr_in *sinptr; 1018 struct sockaddr_in *sinptr;
1031 guint32 lhost = htonl(127 * 256 * 256 * 256 + 1); 1019 guint32 lhost = htonl(127 * 256 * 256 * 256 + 1);
1032 long unsigned int add; 1020 long unsigned int add;
1033 int source = fd; 1021 int source = fd;
1034 int len; 1022 int len, count = 0;
1035 1023
1036 if (fd < 0) 1024 if (fd < 0)
1037 source = socket(PF_INET, SOCK_STREAM, 0); 1025 source = socket(PF_INET, SOCK_STREAM, 0);
1038 1026
1039 ifc.ifc_len = sizeof(buffer); 1027 ifc.ifc_len = sizeof(buffer);
1040 ifc.ifc_req = (struct ifreq *)buffer; 1028 ifc.ifc_req = (struct ifreq *)buffer;
1041 ioctl(source, SIOCGIFCONF, &ifc); 1029 ioctl(source, SIOCGIFCONF, &ifc);
1042 1030
1043 if (fd < 0) 1031 if (fd < 0)
1044 close(source); 1032 close(source);
1045 memset(ip_ext, 0, 17 * 10); 1033
1034 memset(ip_ext, 0, sizeof(ip_ext));
1046 memcpy(ip_ext, "0.0.0.0", 7); 1035 memcpy(ip_ext, "0.0.0.0", 7);
1047 tmp = buffer; 1036 tmp = buffer;
1048 tip = ip_ext; 1037 tip = ip_ext;
1049 while (tmp < buffer + ifc.ifc_len) 1038 while (tmp < buffer + ifc.ifc_len && count < 10)
1050 { 1039 {
1051 ifr = (struct ifreq *)tmp; 1040 ifr = (struct ifreq *)tmp;
1052 tmp += HX_SIZE_OF_IFREQ(*ifr); 1041 tmp += HX_SIZE_OF_IFREQ(*ifr);
1053 1042
1054 if (ifr->ifr_addr.sa_family == AF_INET) 1043 if (ifr->ifr_addr.sa_family == AF_INET)
1060 len = g_snprintf(tip, 17, "%lu.%lu.%lu.%lu;", 1049 len = g_snprintf(tip, 17, "%lu.%lu.%lu.%lu;",
1061 ((add >> 24) & 255), 1050 ((add >> 24) & 255),
1062 ((add >> 16) & 255), 1051 ((add >> 16) & 255),
1063 ((add >> 8) & 255), 1052 ((add >> 8) & 255),
1064 add & 255); 1053 add & 255);
1065 tip = (char*) ((int) tip + len); 1054 tip = &tip[len];
1055 count++;
1066 continue; 1056 continue;
1067 } 1057 }
1068 } 1058 }
1069 } 1059 }
1070 1060