| 26677:04c4a7a7865f | 26725:fbfc67bd9fd6 |
|---|---|
| 86 js->reinit = FALSE; | 86 js->reinit = FALSE; |
| 87 g_free(open_stream); | 87 g_free(open_stream); |
| 88 } | 88 } |
| 89 | 89 |
| 90 static void | 90 static void |
| 91 jabber_session_initialized_cb(JabberStream *js, xmlnode *packet, gpointer data) | 91 jabber_session_initialized_cb(JabberStream *js, const char *from, |
| 92 { | 92 JabberIqType type, const char *id, |
| 93 const char *type = xmlnode_get_attrib(packet, "type"); | 93 xmlnode *packet, gpointer data) |
| 94 if(type && !strcmp(type, "result")) { | 94 { |
| 95 if (type == JABBER_IQ_RESULT) { | |
| 95 jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); | 96 jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); |
| 96 if(js->unregistration) | 97 if(js->unregistration) |
| 97 jabber_unregister_account_cb(js); | 98 jabber_unregister_account_cb(js); |
| 98 } else { | 99 } else { |
| 99 purple_connection_error_reason (js->gc, | 100 purple_connection_error_reason (js->gc, |
| 113 xmlnode_set_namespace(session, "urn:ietf:params:xml:ns:xmpp-session"); | 114 xmlnode_set_namespace(session, "urn:ietf:params:xml:ns:xmpp-session"); |
| 114 | 115 |
| 115 jabber_iq_send(iq); | 116 jabber_iq_send(iq); |
| 116 } | 117 } |
| 117 | 118 |
| 118 static void jabber_bind_result_cb(JabberStream *js, xmlnode *packet, | 119 static void jabber_bind_result_cb(JabberStream *js, const char *from, |
| 119 gpointer data) | 120 JabberIqType type, const char *id, |
| 120 { | 121 xmlnode *packet, gpointer data) |
| 121 const char *type = xmlnode_get_attrib(packet, "type"); | 122 { |
| 122 xmlnode *bind; | 123 xmlnode *bind; |
| 123 | 124 |
| 124 if(type && !strcmp(type, "result") && | 125 if (type == JABBER_IQ_RESULT && |
| 125 (bind = xmlnode_get_child_with_namespace(packet, "bind", "urn:ietf:params:xml:ns:xmpp-bind"))) { | 126 (bind = xmlnode_get_child_with_namespace(packet, "bind", "urn:ietf:params:xml:ns:xmpp-bind"))) { |
| 126 xmlnode *jid; | 127 xmlnode *jid; |
| 127 char *full_jid; | 128 char *full_jid; |
| 128 if((jid = xmlnode_get_child(bind, "jid")) && (full_jid = xmlnode_get_data(jid))) { | 129 if((jid = xmlnode_get_child(bind, "jid")) && (full_jid = xmlnode_get_data(jid))) { |
| 129 JabberBuddy *my_jb = NULL; | 130 JabberBuddy *my_jb = NULL; |
| 447 txt = xmlnode_to_str(packet, &len); | 448 txt = xmlnode_to_str(packet, &len); |
| 448 jabber_send_raw(js, txt, len); | 449 jabber_send_raw(js, txt, len); |
| 449 g_free(txt); | 450 g_free(txt); |
| 450 } | 451 } |
| 451 | 452 |
| 452 static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer unused) | 453 static gboolean jabber_keepalive_timeout(PurpleConnection *gc) |
| 453 { | |
| 454 purple_timeout_remove(js->keepalive_timeout); | |
| 455 js->keepalive_timeout = -1; | |
| 456 } | |
| 457 | |
| 458 static gboolean jabber_pong_timeout(PurpleConnection *gc) | |
| 459 { | 454 { |
| 460 JabberStream *js = gc->proto_data; | 455 JabberStream *js = gc->proto_data; |
| 461 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | 456 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
| 462 _("Ping timeout")); | 457 _("Ping timeout")); |
| 463 js->keepalive_timeout = -1; | 458 js->keepalive_timeout = -1; |
| 467 void jabber_keepalive(PurpleConnection *gc) | 462 void jabber_keepalive(PurpleConnection *gc) |
| 468 { | 463 { |
| 469 JabberStream *js = gc->proto_data; | 464 JabberStream *js = gc->proto_data; |
| 470 | 465 |
| 471 if (js->keepalive_timeout == -1) { | 466 if (js->keepalive_timeout == -1) { |
| 472 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET); | 467 jabber_ping_jid(js, NULL); |
| 473 | 468 js->keepalive_timeout = purple_timeout_add_seconds(120, |
| 474 xmlnode *ping = xmlnode_new_child(iq->node, "ping"); | 469 (GSourceFunc)(jabber_keepalive_timeout), gc); |
| 475 xmlnode_set_namespace(ping, "urn:xmpp:ping"); | |
| 476 | |
| 477 js->keepalive_timeout = purple_timeout_add_seconds(120, (GSourceFunc)(jabber_pong_timeout), gc); | |
| 478 jabber_iq_set_callback(iq, jabber_pong_cb, NULL); | |
| 479 jabber_iq_send(iq); | |
| 480 } | 470 } |
| 481 } | 471 } |
| 482 | 472 |
| 483 static void | 473 static void |
| 484 jabber_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, | 474 jabber_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, |
| 810 { | 800 { |
| 811 purple_timeout_add(0, conn_close_cb, js); | 801 purple_timeout_add(0, conn_close_cb, js); |
| 812 } | 802 } |
| 813 | 803 |
| 814 static void | 804 static void |
| 815 jabber_registration_result_cb(JabberStream *js, xmlnode *packet, gpointer data) | 805 jabber_registration_result_cb(JabberStream *js, const char *from, |
| 806 JabberIqType type, const char *id, | |
| 807 xmlnode *packet, gpointer data) | |
| 816 { | 808 { |
| 817 PurpleAccount *account = purple_connection_get_account(js->gc); | 809 PurpleAccount *account = purple_connection_get_account(js->gc); |
| 818 const char *type = xmlnode_get_attrib(packet, "type"); | |
| 819 char *buf; | 810 char *buf; |
| 820 char *to = data; | 811 char *to = data; |
| 821 | 812 |
| 822 if(!strcmp(type, "result")) { | 813 if (type == JABBER_IQ_RESULT) { |
| 823 if(js->registration) { | 814 if(js->registration) { |
| 824 buf = g_strdup_printf(_("Registration of %s@%s successful"), | 815 buf = g_strdup_printf(_("Registration of %s@%s successful"), |
| 825 js->user->node, js->user->domain); | 816 js->user->node, js->user->domain); |
| 826 if(account->registration_cb) | 817 if(account->registration_cb) |
| 827 (account->registration_cb)(account, TRUE, account->registration_cb_user_data); | 818 (account->registration_cb)(account, TRUE, account->registration_cb_user_data); |
| 845 if(account->registration_cb) | 836 if(account->registration_cb) |
| 846 (account->registration_cb)(account, FALSE, account->registration_cb_user_data); | 837 (account->registration_cb)(account, FALSE, account->registration_cb_user_data); |
| 847 } | 838 } |
| 848 g_free(to); | 839 g_free(to); |
| 849 if(js->registration) | 840 if(js->registration) |
| 850 jabber_connection_schedule_close(js); | 841 jabber_connection_schedule_close(js); |
| 851 } | 842 } |
| 852 | 843 |
| 853 static void | 844 static void |
| 854 jabber_unregistration_result_cb(JabberStream *js, xmlnode *packet, gpointer data) | 845 jabber_unregistration_result_cb(JabberStream *js, const char *from, |
| 855 { | 846 JabberIqType type, const char *id, |
| 856 const char *type = xmlnode_get_attrib(packet, "type"); | 847 xmlnode *packet, gpointer data) |
| 848 { | |
| 857 char *buf; | 849 char *buf; |
| 858 char *to = data; | 850 char *to = data; |
| 859 | 851 |
| 860 /* This function is never called for unregistering our XMPP account from | 852 /* This function is never called for unregistering our XMPP account from |
| 861 * the server, so there should always be a 'to' address. */ | 853 * the server, so there should always be a 'to' address. */ |
| 862 g_return_if_fail(to != NULL); | 854 g_return_if_fail(to != NULL); |
| 863 | 855 |
| 864 if(!strcmp(type, "result")) { | 856 if (type == JABBER_IQ_RESULT) { |
| 865 buf = g_strdup_printf(_("Registration from %s successfully removed"), | 857 buf = g_strdup_printf(_("Registration from %s successfully removed"), |
| 866 to); | 858 to); |
| 867 purple_notify_info(NULL, _("Unregistration Successful"), | 859 purple_notify_info(NULL, _("Unregistration Successful"), |
| 868 _("Unregistration Successful"), buf); | 860 _("Unregistration Successful"), buf); |
| 869 g_free(buf); | 861 g_free(buf); |
| 1008 | 1000 |
| 1009 jabber_iq_set_callback(iq, jabber_registration_result_cb, to); | 1001 jabber_iq_set_callback(iq, jabber_registration_result_cb, to); |
| 1010 jabber_iq_send(iq); | 1002 jabber_iq_send(iq); |
| 1011 } | 1003 } |
| 1012 | 1004 |
| 1013 void jabber_register_parse(JabberStream *js, xmlnode *packet) | 1005 void jabber_register_parse(JabberStream *js, const char *from, JabberIqType type, |
| 1006 const char *id, xmlnode *query) | |
| 1014 { | 1007 { |
| 1015 PurpleAccount *account = purple_connection_get_account(js->gc); | 1008 PurpleAccount *account = purple_connection_get_account(js->gc); |
| 1016 const char *type; | |
| 1017 const char *from; | |
| 1018 PurpleRequestFields *fields; | 1009 PurpleRequestFields *fields; |
| 1019 PurpleRequestFieldGroup *group; | 1010 PurpleRequestFieldGroup *group; |
| 1020 PurpleRequestField *field; | 1011 PurpleRequestField *field; |
| 1021 xmlnode *query, *x, *y; | 1012 xmlnode *x, *y; |
| 1022 char *instructions; | 1013 char *instructions; |
| 1023 JabberRegisterCBData *cbdata; | 1014 JabberRegisterCBData *cbdata; |
| 1024 gboolean registered = FALSE; | 1015 gboolean registered = FALSE; |
| 1025 | 1016 |
| 1026 if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) | 1017 if (type != JABBER_IQ_RESULT) |
| 1027 return; | 1018 return; |
| 1028 | 1019 |
| 1029 from = xmlnode_get_attrib(packet, "from"); | 1020 if (!from) |
| 1021 from = js->serverFQDN; | |
| 1022 g_return_if_fail(from != NULL); | |
| 1030 | 1023 |
| 1031 if(js->registration) { | 1024 if(js->registration) { |
| 1032 /* get rid of the login thingy */ | 1025 /* get rid of the login thingy */ |
| 1033 purple_connection_set_state(js->gc, PURPLE_CONNECTED); | 1026 purple_connection_set_state(js->gc, PURPLE_CONNECTED); |
| 1034 } | 1027 } |
| 1035 | |
| 1036 query = xmlnode_get_child(packet, "query"); | |
| 1037 | 1028 |
| 1038 if(xmlnode_get_child(query, "registered")) { | 1029 if(xmlnode_get_child(query, "registered")) { |
| 1039 registered = TRUE; | 1030 registered = TRUE; |
| 1040 | 1031 |
| 1041 if(js->registration) { | 1032 if(js->registration) { |
| 1270 js); | 1261 js); |
| 1271 } | 1262 } |
| 1272 } | 1263 } |
| 1273 } | 1264 } |
| 1274 | 1265 |
| 1275 static void jabber_unregister_account_iq_cb(JabberStream *js, xmlnode *packet, gpointer data) { | 1266 static void |
| 1267 jabber_unregister_account_iq_cb(JabberStream *js, const char *from, | |
| 1268 JabberIqType type, const char *id, | |
| 1269 xmlnode *packet, gpointer data) | |
| 1270 { | |
| 1276 PurpleAccount *account = purple_connection_get_account(js->gc); | 1271 PurpleAccount *account = purple_connection_get_account(js->gc); |
| 1277 const char *type = xmlnode_get_attrib(packet,"type"); | 1272 |
| 1278 if(!strcmp(type,"error")) { | 1273 if (type == JABBER_IQ_ERROR) { |
| 1279 char *msg = jabber_parse_error(js, packet, NULL); | 1274 char *msg = jabber_parse_error(js, packet, NULL); |
| 1280 | 1275 |
| 1281 purple_notify_error(js->gc, _("Error unregistering account"), | 1276 purple_notify_error(js->gc, _("Error unregistering account"), |
| 1282 _("Error unregistering account"), msg); | 1277 _("Error unregistering account"), msg); |
| 1283 g_free(msg); | 1278 g_free(msg); |
| 1284 if(js->unregistration_cb) | 1279 if(js->unregistration_cb) |
| 1285 js->unregistration_cb(account, FALSE, js->unregistration_user_data); | 1280 js->unregistration_cb(account, FALSE, js->unregistration_user_data); |
| 1286 } else if(!strcmp(type,"result")) { | 1281 } else { |
| 1287 purple_notify_info(js->gc, _("Account successfully unregistered"), | 1282 purple_notify_info(js->gc, _("Account successfully unregistered"), |
| 1288 _("Account successfully unregistered"), NULL); | 1283 _("Account successfully unregistered"), NULL); |
| 1289 if(js->unregistration_cb) | 1284 if(js->unregistration_cb) |
| 1290 js->unregistration_cb(account, TRUE, js->unregistration_user_data); | 1285 js->unregistration_cb(account, TRUE, js->unregistration_user_data); |
| 1291 } | 1286 } |
| 1528 /* send out an updated prescence */ | 1523 /* send out an updated prescence */ |
| 1529 purple_debug_info("jabber", "sending updated presence for idle\n"); | 1524 purple_debug_info("jabber", "sending updated presence for idle\n"); |
| 1530 jabber_presence_send(account, status); | 1525 jabber_presence_send(account, status); |
| 1531 } | 1526 } |
| 1532 | 1527 |
| 1533 static void jabber_blocklist_parse(JabberStream *js, xmlnode *packet, gpointer data) | 1528 static void jabber_blocklist_parse(JabberStream *js, const char *from, |
| 1529 JabberIqType type, const char *id, | |
| 1530 xmlnode *packet, gpointer data) | |
| 1534 { | 1531 { |
| 1535 xmlnode *blocklist, *item; | 1532 xmlnode *blocklist, *item; |
| 1536 PurpleAccount *account; | 1533 PurpleAccount *account; |
| 1537 | 1534 |
| 1538 blocklist = xmlnode_get_child_with_namespace(packet, | 1535 blocklist = xmlnode_get_child_with_namespace(packet, |
| 1980 | 1977 |
| 1981 return types; | 1978 return types; |
| 1982 } | 1979 } |
| 1983 | 1980 |
| 1984 static void | 1981 static void |
| 1985 jabber_password_change_result_cb(JabberStream *js, xmlnode *packet, | 1982 jabber_password_change_result_cb(JabberStream *js, const char *from, |
| 1986 gpointer data) | 1983 JabberIqType type, const char *id, |
| 1987 { | 1984 xmlnode *packet, gpointer data) |
| 1988 const char *type; | 1985 { |
| 1989 | 1986 if (type == JABBER_IQ_RESULT) { |
| 1990 type = xmlnode_get_attrib(packet, "type"); | |
| 1991 | |
| 1992 if(type && !strcmp(type, "result")) { | |
| 1993 purple_notify_info(js->gc, _("Password Changed"), _("Password Changed"), | 1987 purple_notify_info(js->gc, _("Password Changed"), _("Password Changed"), |
| 1994 _("Your password has been changed.")); | 1988 _("Your password has been changed.")); |
| 1995 | 1989 |
| 1996 purple_account_set_password(js->gc->account, (char *)data); | 1990 purple_account_set_password(js->gc->account, (char *)data); |
| 1997 } else { | 1991 } else { |
| 2519 } | 2513 } |
| 2520 | 2514 |
| 2521 static PurpleCmdRet jabber_cmd_ping(PurpleConversation *conv, | 2515 static PurpleCmdRet jabber_cmd_ping(PurpleConversation *conv, |
| 2522 const char *cmd, char **args, char **error, void *data) | 2516 const char *cmd, char **args, char **error, void *data) |
| 2523 { | 2517 { |
| 2518 PurpleAccount *account; | |
| 2519 PurpleConnection *pc; | |
| 2520 | |
| 2524 if(!args || !args[0]) | 2521 if(!args || !args[0]) |
| 2525 return PURPLE_CMD_RET_FAILED; | 2522 return PURPLE_CMD_RET_FAILED; |
| 2526 | 2523 |
| 2527 if(!jabber_ping_jid(conv, args[0])) { | 2524 account = purple_conversation_get_account(conv); |
| 2525 pc = purple_account_get_connection(account); | |
| 2526 | |
| 2527 if(!jabber_ping_jid(purple_connection_get_protocol_data(pc), args[0])) { | |
| 2528 *error = g_strdup_printf(_("Unable to ping user %s"), args[0]); | 2528 *error = g_strdup_printf(_("Unable to ping user %s"), args[0]); |
| 2529 return PURPLE_CMD_RET_FAILED; | 2529 return PURPLE_CMD_RET_FAILED; |
| 2530 } | 2530 } |
| 2531 | 2531 |
| 2532 return PURPLE_CMD_RET_OK; | 2532 return PURPLE_CMD_RET_OK; |
| 2654 gboolean jabber_offline_message(const PurpleBuddy *buddy) | 2654 gboolean jabber_offline_message(const PurpleBuddy *buddy) |
| 2655 { | 2655 { |
| 2656 return TRUE; | 2656 return TRUE; |
| 2657 } | 2657 } |
| 2658 | 2658 |
| 2659 #ifdef USE_VV | |
| 2660 typedef struct { | |
| 2661 PurpleConnection *pc; | |
| 2662 gchar *who; | |
| 2663 PurpleMediaSessionType type; | |
| 2664 | |
| 2665 } JabberMediaRequest; | |
| 2666 | |
| 2667 static void | |
| 2668 jabber_media_cancel_cb(JabberMediaRequest *request, | |
| 2669 PurpleRequestFields *fields) | |
| 2670 { | |
| 2671 g_free(request->who); | |
| 2672 g_free(request); | |
| 2673 } | |
| 2674 | |
| 2675 static void | |
| 2676 jabber_media_ok_cb(JabberMediaRequest *request, PurpleRequestFields *fields) | |
| 2677 { | |
| 2678 PurpleRequestField *field = | |
| 2679 purple_request_fields_get_field(fields, "resource"); | |
| 2680 int selected_id = purple_request_field_choice_get_value(field); | |
| 2681 GList *labels = purple_request_field_choice_get_labels(field); | |
| 2682 gchar *who = g_strdup_printf("%s/%s", request->who, | |
| 2683 (gchar*)g_list_nth_data(labels, selected_id)); | |
| 2684 jabber_initiate_media(request->pc, who, request->type); | |
| 2685 | |
| 2686 g_free(who); | |
| 2687 g_free(request->who); | |
| 2688 g_free(request); | |
| 2689 } | |
| 2690 #endif | |
| 2691 | |
| 2659 gboolean | 2692 gboolean |
| 2660 jabber_initiate_media(PurpleConnection *gc, const char *who, | 2693 jabber_initiate_media(PurpleConnection *gc, const char *who, |
| 2661 PurpleMediaSessionType type) | 2694 PurpleMediaSessionType type) |
| 2662 { | 2695 { |
| 2663 #ifdef USE_VV | 2696 #ifdef USE_VV |
| 2664 JabberStream *js = (JabberStream *) gc->proto_data; | 2697 JabberStream *js = (JabberStream *) gc->proto_data; |
| 2665 JabberBuddy *jb; | 2698 JabberBuddy *jb; |
| 2699 JabberBuddyResource *jbr = NULL; | |
| 2700 char *resource; | |
| 2666 | 2701 |
| 2667 if (!js) { | 2702 if (!js) { |
| 2668 purple_debug_error("jabber", | 2703 purple_debug_error("jabber", |
| 2669 "jabber_initiate_media: NULL stream\n"); | 2704 "jabber_initiate_media: NULL stream\n"); |
| 2670 return FALSE; | 2705 return FALSE; |
| 2671 } | 2706 } |
| 2672 | 2707 |
| 2708 | |
| 2709 if((resource = jabber_get_resource(who)) != NULL) { | |
| 2710 /* they've specified a resource, no need to ask or | |
| 2711 * default or anything, just do it */ | |
| 2712 | |
| 2713 jb = jabber_buddy_find(js, who, FALSE); | |
| 2714 jbr = jabber_buddy_find_resource(jb, resource); | |
| 2715 g_free(resource); | |
| 2716 | |
| 2717 if (type & PURPLE_MEDIA_AUDIO && | |
| 2718 !jabber_resource_has_capability(jbr, | |
| 2719 JINGLE_APP_RTP_SUPPORT_AUDIO) && | |
| 2720 jabber_resource_has_capability(jbr, | |
| 2721 GOOGLE_VOICE_CAP)) | |
| 2722 return jabber_google_session_initiate( | |
| 2723 gc->proto_data, who, type); | |
| 2724 else | |
| 2725 return jingle_rtp_initiate_media( | |
| 2726 gc->proto_data, who, type); | |
| 2727 } | |
| 2728 | |
| 2673 jb = jabber_buddy_find(js, who, FALSE); | 2729 jb = jabber_buddy_find(js, who, FALSE); |
| 2674 | 2730 |
| 2675 if (!jb) { | 2731 if(!jb || !jb->resources) { |
| 2676 purple_debug_error("jabber", "Could not find buddy\n"); | 2732 /* no resources online, we're trying to initiate with someone |
| 2733 * whose presence we're not subscribed to, or | |
| 2734 * someone who is offline. Let's inform the user */ | |
| 2735 char *msg; | |
| 2736 | |
| 2737 if(!jb) { | |
| 2738 msg = g_strdup_printf(_("Unable to initiate media with %s: invalid JID"), who); | |
| 2739 } else if(jb->subscription & JABBER_SUB_TO) { | |
| 2740 msg = g_strdup_printf(_("Unable to initiate media with %s: user is not online"), who); | |
| 2741 } else { | |
| 2742 msg = g_strdup_printf(_("Unable to initiate media with %s: not subscribed to user presence"), who); | |
| 2743 } | |
| 2744 | |
| 2745 purple_notify_error(js->gc, _("Media Initiation Failed"), | |
| 2746 _("Media Initiation Failed"), msg); | |
| 2747 g_free(msg); | |
| 2677 return FALSE; | 2748 return FALSE; |
| 2678 } | 2749 } else if(!jb->resources->next) { |
| 2679 | 2750 /* only 1 resource online (probably our most common case) |
| 2680 if (type & PURPLE_MEDIA_AUDIO && | 2751 * so no need to ask who to initiate with */ |
| 2681 !jabber_buddy_has_capability(jb, | 2752 gchar *name; |
| 2682 JINGLE_APP_RTP_SUPPORT_AUDIO) && | 2753 gboolean result; |
| 2683 jabber_buddy_has_capability(jb, GOOGLE_VOICE_CAP)) | 2754 jbr = jb->resources->data; |
| 2684 return jabber_google_session_initiate(gc->proto_data, who, type); | 2755 name = g_strdup_printf("%s/%s", who, jbr->name); |
| 2685 else | 2756 result = jabber_initiate_media(gc, name, type); |
| 2686 return jingle_rtp_initiate_media(gc->proto_data, who, type); | 2757 g_free(name); |
| 2687 #else | 2758 return result; |
| 2759 } else { | |
| 2760 /* we've got multiple resources, | |
| 2761 * we need to pick one to initiate with */ | |
| 2762 GList *l; | |
| 2763 char *msg; | |
| 2764 PurpleRequestFields *fields; | |
| 2765 PurpleRequestField *field = purple_request_field_choice_new( | |
| 2766 "resource", _("Resource"), 0); | |
| 2767 PurpleRequestFieldGroup *group; | |
| 2768 JabberMediaRequest *request; | |
| 2769 | |
| 2770 for(l = jb->resources; l; l = l->next) | |
| 2771 { | |
| 2772 JabberBuddyResource *ljbr = l->data; | |
| 2773 PurpleMediaCaps caps; | |
| 2774 gchar *name; | |
| 2775 name = g_strdup_printf("%s/%s", who, ljbr->name); | |
| 2776 caps = jabber_get_media_caps(gc, name); | |
| 2777 g_free(name); | |
| 2778 | |
| 2779 if ((type & PURPLE_MEDIA_AUDIO) && | |
| 2780 (type & PURPLE_MEDIA_VIDEO)) { | |
| 2781 if (caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO) { | |
| 2782 jbr = ljbr; | |
| 2783 purple_request_field_choice_add( | |
| 2784 field, jbr->name); | |
| 2785 } | |
| 2786 } else if (type & (PURPLE_MEDIA_AUDIO) && | |
| 2787 (caps & PURPLE_MEDIA_CAPS_AUDIO)) { | |
| 2788 jbr = ljbr; | |
| 2789 purple_request_field_choice_add( | |
| 2790 field, jbr->name); | |
| 2791 }else if (type & (PURPLE_MEDIA_VIDEO) && | |
| 2792 (caps & PURPLE_MEDIA_CAPS_VIDEO)) { | |
| 2793 jbr = ljbr; | |
| 2794 purple_request_field_choice_add( | |
| 2795 field, jbr->name); | |
| 2796 } | |
| 2797 } | |
| 2798 | |
| 2799 if (jbr == NULL) { | |
| 2800 purple_debug_error("jabber", | |
| 2801 "No resources available\n"); | |
| 2802 return FALSE; | |
| 2803 } | |
| 2804 | |
| 2805 if (g_list_length(purple_request_field_choice_get_labels( | |
| 2806 field)) <= 1) { | |
| 2807 gchar *name; | |
| 2808 gboolean result; | |
| 2809 purple_request_field_destroy(field); | |
| 2810 name = g_strdup_printf("%s/%s", who, jbr->name); | |
| 2811 result = jabber_initiate_media(gc, name, type); | |
| 2812 g_free(name); | |
| 2813 return result; | |
| 2814 } | |
| 2815 | |
| 2816 msg = g_strdup_printf(_("Please select the resource of %s with which you would like to start a media session."), who); | |
| 2817 fields = purple_request_fields_new(); | |
| 2818 group = purple_request_field_group_new(NULL); | |
| 2819 request = g_new0(JabberMediaRequest, 1); | |
| 2820 request->pc = gc; | |
| 2821 request->who = g_strdup(who); | |
| 2822 request->type = type; | |
| 2823 | |
| 2824 purple_request_field_group_add_field(group, field); | |
| 2825 purple_request_fields_add_group(fields, group); | |
| 2826 purple_request_fields(gc, _("Select a Resource"), msg, NULL, | |
| 2827 fields, _("Initiate Media"), | |
| 2828 G_CALLBACK(jabber_media_ok_cb), _("Cancel"), | |
| 2829 G_CALLBACK(jabber_media_cancel_cb), | |
| 2830 gc->account, who, NULL, request); | |
| 2831 | |
| 2832 g_free(msg); | |
| 2833 return TRUE; | |
| 2834 } | |
| 2835 #endif | |
| 2688 return FALSE; | 2836 return FALSE; |
| 2689 #endif | |
| 2690 } | 2837 } |
| 2691 | 2838 |
| 2692 PurpleMediaCaps jabber_get_media_caps(PurpleConnection *gc, const char *who) | 2839 PurpleMediaCaps jabber_get_media_caps(PurpleConnection *gc, const char *who) |
| 2693 { | 2840 { |
| 2694 #ifdef USE_VV | 2841 #ifdef USE_VV |
| 2695 JabberStream *js = (JabberStream *) gc->proto_data; | 2842 JabberStream *js = (JabberStream *) gc->proto_data; |
| 2696 JabberBuddy *jb; | 2843 JabberBuddy *jb; |
| 2844 JabberBuddyResource *jbr; | |
| 2697 PurpleMediaCaps caps = PURPLE_MEDIA_CAPS_NONE; | 2845 PurpleMediaCaps caps = PURPLE_MEDIA_CAPS_NONE; |
| 2846 gchar *resource; | |
| 2698 | 2847 |
| 2699 if (!js) { | 2848 if (!js) { |
| 2700 purple_debug_info("jabber", | 2849 purple_debug_info("jabber", |
| 2701 "jabber_can_do_media: NULL stream\n"); | 2850 "jabber_can_do_media: NULL stream\n"); |
| 2702 return FALSE; | 2851 return FALSE; |
| 2703 } | 2852 } |
| 2704 | 2853 |
| 2854 if ((resource = jabber_get_resource(who)) != NULL) { | |
| 2855 /* they've specified a resource, no need to ask or | |
| 2856 * default or anything, just do it */ | |
| 2857 | |
| 2858 jb = jabber_buddy_find(js, who, FALSE); | |
| 2859 jbr = jabber_buddy_find_resource(jb, resource); | |
| 2860 g_free(resource); | |
| 2861 | |
| 2862 if (!jbr) { | |
| 2863 purple_debug_error("jabber", "jabber_get_media_caps:" | |
| 2864 " Can't find resource %s\n", who); | |
| 2865 return caps; | |
| 2866 } | |
| 2867 | |
| 2868 if (jabber_resource_has_capability(jbr, | |
| 2869 JINGLE_APP_RTP_SUPPORT_AUDIO)) | |
| 2870 caps |= PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION | | |
| 2871 PURPLE_MEDIA_CAPS_AUDIO; | |
| 2872 if (jabber_resource_has_capability(jbr, | |
| 2873 JINGLE_APP_RTP_SUPPORT_VIDEO)) | |
| 2874 caps |= PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION | | |
| 2875 PURPLE_MEDIA_CAPS_VIDEO; | |
| 2876 if (caps & PURPLE_MEDIA_CAPS_AUDIO && caps & | |
| 2877 PURPLE_MEDIA_CAPS_VIDEO) | |
| 2878 caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO; | |
| 2879 if (caps != PURPLE_MEDIA_CAPS_NONE) { | |
| 2880 if (!jabber_resource_has_capability(jbr, | |
| 2881 JINGLE_TRANSPORT_ICEUDP) && | |
| 2882 !jabber_resource_has_capability(jbr, | |
| 2883 JINGLE_TRANSPORT_RAWUDP)) { | |
| 2884 purple_debug_info("jingle-rtp", "Buddy doesn't " | |
| 2885 "support the same transport types\n"); | |
| 2886 caps = PURPLE_MEDIA_CAPS_NONE; | |
| 2887 } else | |
| 2888 caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION | | |
| 2889 PURPLE_MEDIA_CAPS_CHANGE_DIRECTION; | |
| 2890 } | |
| 2891 if (jabber_resource_has_capability(jbr, GOOGLE_VOICE_CAP)) | |
| 2892 caps |= PURPLE_MEDIA_CAPS_AUDIO; | |
| 2893 return caps; | |
| 2894 } | |
| 2895 | |
| 2705 jb = jabber_buddy_find(js, who, FALSE); | 2896 jb = jabber_buddy_find(js, who, FALSE); |
| 2706 | 2897 |
| 2707 if (!jb) { | 2898 if(!jb || !jb->resources) { |
| 2708 purple_debug_error("jabber", "Could not find buddy\n"); | 2899 /* no resources online, we're trying to get caps for someone |
| 2709 return FALSE; | 2900 * whose presence we're not subscribed to, or |
| 2710 } | 2901 * someone who is offline. */ |
| 2711 | 2902 return caps; |
| 2712 if (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_AUDIO)) | 2903 } else if(!jb->resources->next) { |
| 2713 caps |= PURPLE_MEDIA_CAPS_AUDIO | | 2904 /* only 1 resource online (probably our most common case) */ |
| 2714 PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION; | 2905 gchar *name; |
| 2715 if (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_VIDEO)) | 2906 jbr = jb->resources->data; |
| 2716 caps |= PURPLE_MEDIA_CAPS_VIDEO | | 2907 name = g_strdup_printf("%s/%s", who, jbr->name); |
| 2717 PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION; | 2908 caps = jabber_get_media_caps(gc, name); |
| 2718 if (caps & PURPLE_MEDIA_CAPS_AUDIO && caps & PURPLE_MEDIA_CAPS_VIDEO) | 2909 g_free(name); |
| 2719 caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO; | 2910 } else { |
| 2720 if (caps != PURPLE_MEDIA_CAPS_NONE) { | 2911 /* we've got multiple resources, combine their caps */ |
| 2721 if (!jabber_buddy_has_capability(jb, | 2912 GList *l; |
| 2722 JINGLE_TRANSPORT_ICEUDP) && | 2913 |
| 2723 !jabber_buddy_has_capability(jb, | 2914 for(l = jb->resources; l; l = l->next) |
| 2724 JINGLE_TRANSPORT_RAWUDP)) { | 2915 { |
| 2725 purple_debug_info("jingle-rtp", "Buddy doesn't " | 2916 gchar *name; |
| 2726 "support the same transport types\n"); | 2917 jbr = l->data; |
| 2727 caps = PURPLE_MEDIA_CAPS_NONE; | 2918 name = g_strdup_printf("%s/%s", who, jbr->name); |
| 2728 } else | 2919 caps |= jabber_get_media_caps(gc, name); |
| 2729 caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION | | 2920 g_free(name); |
| 2730 PURPLE_MEDIA_CAPS_CHANGE_DIRECTION; | 2921 } |
| 2731 } | 2922 } |
| 2732 if (jabber_buddy_has_capability(jb, GOOGLE_VOICE_CAP)) | |
| 2733 caps |= PURPLE_MEDIA_CAPS_AUDIO; | |
| 2734 | 2923 |
| 2735 return caps; | 2924 return caps; |
| 2736 #else | 2925 #else |
| 2737 return PURPLE_MEDIA_CAPS_NONE; | 2926 return PURPLE_MEDIA_CAPS_NONE; |
| 2738 #endif | 2927 #endif |