# HG changeset patch # User Marcus Lundblad # Date 1232665492 0 # Node ID c56e8826fed005973109f918f119565b0b104eb2 # Parent d68924f1265faba06a5daace76fd3e18c0c8512f Added support to generate relayed candidates (TURN). Added prefs setting for relay server in Pidgin diff -r d68924f1265f -r c56e8826fed0 libpurple/media.c --- a/libpurple/media.c Mon Jan 19 10:47:12 2009 +0000 +++ b/libpurple/media.c Thu Jan 22 23:04:52 2009 +0000 @@ -1622,23 +1622,70 @@ GError *err = NULL; FsStream *fsstream = NULL; const gchar *stun_ip = purple_network_get_stun_ip(); - + const gchar *turn_ip = purple_network_get_turn_ip(); - if (stun_ip) { - GParameter *param = g_new0(GParameter, num_params+1); + if (stun_ip || turn_ip) { + guint new_num_params = + stun_ip && turn_ip ? num_params + 2 : num_params + 1; + guint next_param_index = num_params; + GParameter *param = g_new0(GParameter, new_num_params); memcpy(param, params, sizeof(GParameter) * num_params); - purple_debug_info("media", - "setting property stun-ip on new stream: %s\n", stun_ip); + if (stun_ip) { + purple_debug_info("media", + "setting property stun-ip on new stream: %s\n", stun_ip); + + param[next_param_index].name = "stun-ip"; + g_value_init(¶m[next_param_index].value, G_TYPE_STRING); + g_value_set_string(¶m[next_param_index].value, stun_ip); + next_param_index++; + } - param[num_params].name = "stun-ip"; - g_value_init(¶m[num_params].value, G_TYPE_STRING); - g_value_set_string(¶m[num_params].value, stun_ip); + if (turn_ip) { + GValueArray *relay_info = g_value_array_new(0); + GValue value = {0}; + gint turn_port = + purple_prefs_get_int("/purple/network/turn_port"); + const gchar *username = + purple_prefs_get_string("/purple/network/turn_username"); + const gchar *password = + purple_prefs_get_string("/purple/network/turn_password"); + GstStructure *turn_setup = gst_structure_new("relay-info", + "ip", G_TYPE_STRING, turn_ip, + "port", G_TYPE_UINT, turn_port, + "username", G_TYPE_STRING, username, + "password", G_TYPE_STRING, password, + NULL); + if (turn_setup) { + g_value_init(&value, GST_TYPE_STRUCTURE); + gst_value_set_structure(&value, turn_setup); + relay_info = g_value_array_append(relay_info, &value); + gst_structure_free(turn_setup); + + purple_debug_info("media", + "setting property relay-info on new stream\n"); + param[next_param_index].name = "relay-info"; + g_value_init(¶m[next_param_index].value, + G_TYPE_VALUE_ARRAY); + g_value_set_boxed(¶m[next_param_index].value, + relay_info); + g_value_array_free(relay_info); + } else { + purple_debug_error("media", "Error relay info"); + g_object_unref(participant); + g_hash_table_remove(media->priv->participants, who); + purple_media_remove_session(media, session); + g_free(session); + return FALSE; + } + + } + fsstream = fs_session_new_stream(session->session, participant, type_direction & FS_DIRECTION_RECV, transmitter, - num_params+1, param, &err); + new_num_params, param, &err); g_free(param); } else { fsstream = fs_session_new_stream(session->session, diff -r d68924f1265f -r c56e8826fed0 libpurple/network.c --- a/libpurple/network.c Mon Jan 19 10:47:12 2009 +0000 +++ b/libpurple/network.c Thu Jan 22 23:04:52 2009 +0000 @@ -93,8 +93,9 @@ static NMState nm_get_network_state(void); #endif -/* Cached IP address for STUN server */ +/* Cached IP addresses for STUN and TURN servers (set globally in prefs) */ static gchar *stun_ip = NULL; +static gchar *turn_ip = NULL; const unsigned char * purple_network_ip_atoi(const char *ip) @@ -694,6 +695,8 @@ offline */ purple_network_set_stun_server( purple_prefs_get_string("/purple/network/stun_server")); + purple_network_set_turn_server( + purple_prefs_get_string("/purple/network/turn_server")); if (ui_ops != NULL && ui_ops->network_connected != NULL) ui_ops->network_connected(); @@ -757,11 +760,13 @@ #endif static void -purple_network_stun_lookup_cb(GSList *hosts, gpointer data, +purple_network_ip_lookup_cb(GSList *hosts, gpointer data, const char *error_message) { + const gchar **ip = (const gchar **) data; + if (error_message) { - purple_debug_error("network", "lookup of STUN server IP failed: %s\n", + purple_debug_error("network", "lookup of IP address failed: %s\n", error_message); g_slist_free(hosts); return; @@ -780,8 +785,8 @@ dst, sizeof(dst)); } - stun_ip = g_strdup(dst); - purple_debug_info("network", "set STUN IP: %s\n", stun_ip); + *ip = g_strdup(dst); + purple_debug_info("network", "set IP address: %s\n", *ip); } g_slist_free(hosts); @@ -793,8 +798,8 @@ if (stun_server && stun_server[0] != '\0') { if (purple_network_is_available()) { purple_debug_info("network", "running DNS query for STUN server\n"); - purple_dnsquery_a(stun_server, 3478, purple_network_stun_lookup_cb, - NULL); + purple_dnsquery_a(stun_server, 3478, purple_network_ip_lookup_cb, + &stun_ip); } else { purple_debug_info("network", "network is unavailable, don't try to update STUN IP"); @@ -805,12 +810,38 @@ } } +void +purple_network_set_turn_server(const gchar *turn_server) +{ + if (turn_server && turn_server[0] != '\0') { + if (purple_network_is_available()) { + purple_debug_info("network", "running DNS query for TURN server\n"); + purple_dnsquery_a(turn_server, + purple_prefs_get_int("/purple/network/turn_port"), + purple_network_ip_lookup_cb, &turn_ip); + } else { + purple_debug_info("network", + "network is unavailable, don't try to update TURN IP"); + } + } else if (turn_ip) { + g_free(turn_ip); + turn_ip = NULL; + } +} + + const gchar * purple_network_get_stun_ip(void) { return stun_ip; } +const gchar * +purple_network_get_turn_ip(void) +{ + return turn_ip; +} + void * purple_network_get_handle(void) { @@ -843,6 +874,10 @@ purple_prefs_add_none ("/purple/network"); purple_prefs_add_string("/purple/network/stun_server", ""); + purple_prefs_add_string("/purple/network/turn_server", ""); + purple_prefs_add_int ("/purple/network/turn_port", 3478); + purple_prefs_add_string("/purple/network/turn_username", ""); + purple_prefs_add_string("/purple/network/turn_password", ""); purple_prefs_add_bool ("/purple/network/auto_ip", TRUE); purple_prefs_add_string("/purple/network/public_ip", ""); purple_prefs_add_bool ("/purple/network/map_ports", TRUE); @@ -884,6 +919,8 @@ purple_network_set_stun_server( purple_prefs_get_string("/purple/network/stun_server")); + purple_network_set_turn_server( + purple_prefs_get_string("/purple/network/turn_server")); } void diff -r d68924f1265f -r c56e8826fed0 libpurple/network.h --- a/libpurple/network.h Mon Jan 19 10:47:12 2009 +0000 +++ b/libpurple/network.h Thu Jan 22 23:04:52 2009 +0000 @@ -215,7 +215,7 @@ void *purple_network_get_handle(void); /** - * Update the STUN server name + * Update the STUN server IP given the host name * Will result in a DNS query being executed asynchronous * * @param stun_server The host name of the STUN server to set @@ -229,6 +229,22 @@ */ const gchar *purple_network_get_stun_ip(void); +/** + * Update the TURN server IP given the host name + * Will result in a DNS query being executed asynchronous + * + * @param stun_server The host name of the STUN server to set + */ +void purple_network_set_turn_server(const gchar *stun_server); + +/** + * Get the IP address of the STUN server as a string representation + * + * @return the IP address + */ +const gchar *purple_network_get_turn_ip(void); + + /** * Initializes the network subsystem. */ diff -r d68924f1265f -r c56e8826fed0 pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Mon Jan 19 10:47:12 2009 +0000 +++ b/pidgin/gtkprefs.c Thu Jan 22 23:04:52 2009 +0000 @@ -137,6 +137,26 @@ return pidgin_add_widget_to_vbox(GTK_BOX(page), title, sg, entry, TRUE, NULL); } +GtkWidget * +pidgin_prefs_labeled_password(GtkWidget *page, const gchar *title, + const char *key, GtkSizeGroup *sg) +{ + GtkWidget *entry; + const gchar *value; + + value = purple_prefs_get_string(key); + + entry = gtk_entry_new(); + gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); + gtk_entry_set_text(GTK_ENTRY(entry), value); + g_signal_connect(G_OBJECT(entry), "changed", + G_CALLBACK(entry_set), (char*)key); + gtk_widget_show(entry); + + return pidgin_add_widget_to_vbox(GTK_BOX(page), title, sg, entry, TRUE, NULL); +} + + static void dropdown_set(GObject *w, const char *key) { @@ -1153,6 +1173,17 @@ return FALSE; } +static gboolean network_turn_server_changed_cb(GtkWidget *widget, + GdkEventFocus *event, gpointer data) +{ + GtkEntry *entry = GTK_ENTRY(widget); + purple_prefs_set_string("/purple/network/turn_server", + gtk_entry_get_text(entry)); + purple_network_set_turn_server(gtk_entry_get_text(entry)); + + return FALSE; +} + static void proxy_changed_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) @@ -1314,6 +1345,43 @@ g_signal_connect(G_OBJECT(ports_checkbox), "clicked", G_CALLBACK(pidgin_toggle_sensitive), spin_button); + vbox = pidgin_make_frame(ret, _("Relay Server (TURN)")); + + /* TURN server */ + hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + label = gtk_label_new_with_mnemonic(_("_Server:")); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + entry = gtk_entry_new(); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry); + g_signal_connect(G_OBJECT(entry), "focus-out-event", + G_CALLBACK(network_turn_server_changed_cb), NULL); + gtk_entry_set_text(GTK_ENTRY(entry), + purple_prefs_get_string("/purple/network/turn_server")); + gtk_misc_set_alignment(GTK_MISC(entry), 0, 0.5); + gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0); + + gtk_size_group_add_widget(GTK_SIZE_GROUP(sg), label); + gtk_size_group_add_widget(GTK_SIZE_GROUP(sg), entry); + + sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + spin_button = pidgin_prefs_labeled_spin_button(hbox, _("_Port:"), + "/purple/network/turn_port", 0, 65535, sg); + gtk_container_add(GTK_CONTAINER(vbox), hbox); + + hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + entry = pidgin_prefs_labeled_entry(hbox, "_User name:", + "/purple/network/turn_username", sg); + + sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + entry = pidgin_prefs_labeled_password(hbox, "_Password:", + "/purple/network/turn_password", sg); + gtk_container_add(GTK_CONTAINER(vbox), hbox); + + if (purple_running_gnome()) { vbox = pidgin_make_frame(ret, _("Proxy Server & Browser")); prefs_proxy_frame = gtk_vbox_new(FALSE, 0); diff -r d68924f1265f -r c56e8826fed0 pidgin/gtkprefs.h --- a/pidgin/gtkprefs.h Mon Jan 19 10:47:12 2009 +0000 +++ b/pidgin/gtkprefs.h Thu Jan 22 23:04:52 2009 +0000 @@ -82,6 +82,22 @@ const char *key, GtkSizeGroup *sg); /** + * Add a new entry representing a password (string) preference + * The entry will use a password-style text entry (the text is substituded) + * + * @param page The page to which the entry will be added + * @param title The text to be displayed as the entry label + * @param key The key of the string pref that will be represented by the entry + * @param sg If not NULL, the size group to which the entry will be added + * + * @return An hbox containing both the label and the entry. Can be used to set + * the widgets to sensitive or insensitive based on the value of a + * checkbox. + */ +GtkWidget *pidgin_prefs_labeled_password(GtkWidget *page, const gchar *title, + const char *key, GtkSizeGroup *sg); + +/** * Add a new dropdown representing a preference of the specified type * * @param page The page to which the dropdown will be added