diff options
author | <ole.andre.ravnaas@collabora.co.uk> | 2006-05-04 16:41:48 +0000 |
---|---|---|
committer | <ole.andre.ravnaas@collabora.co.uk> | 2006-05-04 16:41:48 +0000 |
commit | a9d9b3e89a98652a6c8ecf6e521d8dd816def7bd (patch) | |
tree | 0e609970b903d419cf174f5cbe92fc5d532216f9 | |
parent | 817ff292957a6e05f19e6bd634b9f3fe574b1188 (diff) |
Add a "low-bandwidth" option to GabbleConnectionManager and GabbleConnection, and make GabbleMucChannel poll for room property changes every 5th minute in low bandwidth mode and every minute in high bandwidth mode. Don't change and emit changed for room properties being changed to the same value as they previously were. Free room properties in finalize (doh). Add missing "stun-*" property badgering in GabbleConnectionManager.
-rw-r--r-- | data/gabble.manager | 2 | ||||
-rw-r--r-- | src/gabble-connection-manager.c | 51 | ||||
-rw-r--r-- | src/gabble-connection.c | 18 | ||||
-rw-r--r-- | src/gabble-muc-channel.c | 178 |
4 files changed, 213 insertions, 36 deletions
diff --git a/data/gabble.manager b/data/gabble.manager index 75014a8a..2ec79abb 100644 --- a/data/gabble.manager +++ b/data/gabble.manager @@ -6,6 +6,6 @@ Protos = jabber [Proto jabber] MandatoryParams = s:account,s:password -OptionalParams = s:server,s:resource,q:port,b:old-ssl,b:register,s:https-proxy-server,q:https-proxy-port,s:fallback-conference-server,s:stun-server,q:stun-port,s:stun-relay-magic-cookie,s:stun-relay-server,q:stun-relay-udp-port,q:stun-relay-tcp-port,q:stun-relay-ssltcp-port,s:stun-relay-username,s:stun-relay-password +OptionalParams = s:server,s:resource,q:port,b:old-ssl,b:register,b:low-bandwidth,s:https-proxy-server,q:https-proxy-port,s:fallback-conference-server,s:stun-server,q:stun-port,s:stun-relay-magic-cookie,s:stun-relay-server,q:stun-relay-udp-port,q:stun-relay-tcp-port,q:stun-relay-ssltcp-port,s:stun-relay-username,s:stun-relay-password default-port = 5222 default-old-ssl = 0 diff --git a/src/gabble-connection-manager.c b/src/gabble-connection-manager.c index 0efdc47d..7f5ffa88 100644 --- a/src/gabble-connection-manager.c +++ b/src/gabble-connection-manager.c @@ -145,6 +145,7 @@ struct _GabbleParams { guint port; gboolean old_ssl; gboolean do_register; + gboolean low_bandwidth; gchar *https_proxy_server; guint https_proxy_port; gchar *fallback_conference_server; @@ -178,9 +179,19 @@ enum { JABBER_PARAM_PORT, JABBER_PARAM_OLD_SSL, JABBER_PARAM_REGISTER, + JABBER_PARAM_LOW_BANDWIDTH, JABBER_PARAM_HTTPS_PROXY_SERVER, JABBER_PARAM_HTTPS_PROXY_PORT, JABBER_PARAM_FALLBACK_CONFERENCE_SERVER, + JABBER_PARAM_STUN_SERVER, + JABBER_PARAM_STUN_PORT, + JABBER_PARAM_STUN_RELAY_MAGIC_COOKIE, + JABBER_PARAM_STUN_RELAY_SERVER, + JABBER_PARAM_STUN_RELAY_UDP_PORT, + JABBER_PARAM_STUN_RELAY_TCP_PORT, + JABBER_PARAM_STUN_RELAY_SSLTCP_PORT, + JABBER_PARAM_STUN_RELAY_USERNAME, + JABBER_PARAM_STUN_RELAY_PASSWORD, }; static const GabbleParamSpec jabber_params[] = { @@ -191,6 +202,7 @@ static const GabbleParamSpec jabber_params[] = { { "port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT, FALSE, GINT_TO_POINTER(GABBLE_PARAMS_DEFAULT_PORT), G_STRUCT_OFFSET(GabbleParams, port) }, { "old-ssl", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, FALSE, GINT_TO_POINTER(GABBLE_PARAMS_DEFAULT_OLD_SSL), G_STRUCT_OFFSET(GabbleParams, old_ssl) }, { "register", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, FALSE, GINT_TO_POINTER(FALSE), G_STRUCT_OFFSET(GabbleParams, do_register) }, + { "low-bandwidth", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, FALSE, GINT_TO_POINTER(FALSE), G_STRUCT_OFFSET(GabbleParams, low_bandwidth) }, { "https-proxy-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, FALSE, GABBLE_PARAMS_DEFAULT_HTTPS_PROXY_SERVER, G_STRUCT_OFFSET(GabbleParams, https_proxy_server) }, { "https-proxy-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT, FALSE, GINT_TO_POINTER(GABBLE_PARAMS_DEFAULT_HTTPS_PROXY_PORT), G_STRUCT_OFFSET(GabbleParams, https_proxy_port) }, { "fallback-conference-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, FALSE, GABBLE_PARAMS_DEFAULT_FALLBACK_CONFERENCE_SERVER, G_STRUCT_OFFSET(GabbleParams, fallback_conference_server) }, @@ -518,18 +530,49 @@ gboolean gabble_connection_manager_connect (GabbleConnectionManager *obj, const "password", params.password, NULL); - SET_PROPERTY_IF_PARAM_SET ("resource", JABBER_PARAM_RESOURCE, params.resource); - SET_PROPERTY_IF_PARAM_SET ("connect-server", JABBER_PARAM_SERVER, params.server); + SET_PROPERTY_IF_PARAM_SET ("connect-server", JABBER_PARAM_SERVER, + params.server); + SET_PROPERTY_IF_PARAM_SET ("resource", JABBER_PARAM_RESOURCE, + params.resource); SET_PROPERTY_IF_PARAM_SET ("port", JABBER_PARAM_PORT, params.port); SET_PROPERTY_IF_PARAM_SET ("old-ssl", JABBER_PARAM_OLD_SSL, params.old_ssl); - SET_PROPERTY_IF_PARAM_SET ("register", JABBER_PARAM_REGISTER, params.do_register); - SET_PROPERTY_IF_PARAM_SET ("https-proxy-server", JABBER_PARAM_HTTPS_PROXY_SERVER, + SET_PROPERTY_IF_PARAM_SET ("register", JABBER_PARAM_REGISTER, + params.do_register); + SET_PROPERTY_IF_PARAM_SET ("low-bandwidth", JABBER_PARAM_LOW_BANDWIDTH, + params.low_bandwidth); + SET_PROPERTY_IF_PARAM_SET ("https-proxy-server", + JABBER_PARAM_HTTPS_PROXY_SERVER, params.https_proxy_server); SET_PROPERTY_IF_PARAM_SET ("https-proxy-port", JABBER_PARAM_HTTPS_PROXY_PORT, params.https_proxy_port); SET_PROPERTY_IF_PARAM_SET ("fallback-conference-server", JABBER_PARAM_FALLBACK_CONFERENCE_SERVER, params.fallback_conference_server); + SET_PROPERTY_IF_PARAM_SET ("stun-server", JABBER_PARAM_STUN_SERVER, + params.stun_server); + SET_PROPERTY_IF_PARAM_SET ("stun-port", JABBER_PARAM_STUN_PORT, + params.stun_port); + SET_PROPERTY_IF_PARAM_SET ("stun-relay-magic-cookie", + JABBER_PARAM_STUN_RELAY_MAGIC_COOKIE, + params.stun_relay_magic_cookie); + SET_PROPERTY_IF_PARAM_SET ("stun-relay-server", + JABBER_PARAM_STUN_RELAY_SERVER, + params.stun_relay_server); + SET_PROPERTY_IF_PARAM_SET ("stun-relay-udp-port", + JABBER_PARAM_STUN_RELAY_UDP_PORT, + params.stun_relay_udp_port); + SET_PROPERTY_IF_PARAM_SET ("stun-relay-tcp-port", + JABBER_PARAM_STUN_RELAY_TCP_PORT, + params.stun_relay_tcp_port); + SET_PROPERTY_IF_PARAM_SET ("stun-relay-ssltcp-port", + JABBER_PARAM_STUN_RELAY_SSLTCP_PORT, + params.stun_relay_ssltcp_port); + SET_PROPERTY_IF_PARAM_SET ("stun-relay-username", + JABBER_PARAM_STUN_RELAY_USERNAME, + params.stun_relay_username); + SET_PROPERTY_IF_PARAM_SET ("stun-relay-password", + JABBER_PARAM_STUN_RELAY_PASSWORD, + params.stun_relay_password); /* split up account into username, stream-server and resource */ if (!_gabble_connection_set_properties_from_account (conn, params.account, error)) diff --git a/src/gabble-connection.c b/src/gabble-connection.c index 45becf6d..cb7d3e8c 100644 --- a/src/gabble-connection.c +++ b/src/gabble-connection.c @@ -130,6 +130,7 @@ enum PROP_PORT, PROP_OLD_SSL, PROP_REGISTER, + PROP_LOW_BANDWIDTH, PROP_STREAM_SERVER, PROP_USERNAME, PROP_PASSWORD, @@ -174,6 +175,8 @@ struct _GabbleConnectionPrivate gboolean do_register; + gboolean low_bandwidth; + gchar *https_proxy_server; guint https_proxy_port; @@ -288,6 +291,9 @@ gabble_connection_get_property (GObject *object, case PROP_REGISTER: g_value_set_boolean (value, priv->do_register); break; + case PROP_LOW_BANDWIDTH: + g_value_set_boolean (value, priv->low_bandwidth); + break; case PROP_USERNAME: g_value_set_string (value, priv->username); break; @@ -366,6 +372,9 @@ gabble_connection_set_property (GObject *object, case PROP_REGISTER: priv->do_register = g_value_get_boolean (value); break; + case PROP_LOW_BANDWIDTH: + priv->low_bandwidth = g_value_get_boolean (value); + break; case PROP_STREAM_SERVER: g_free (priv->stream_server); priv->stream_server = g_value_dup_string (value); @@ -490,6 +499,15 @@ gabble_connection_class_init (GabbleConnectionClass *gabble_connection_class) G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_REGISTER, param_spec); + param_spec = g_param_spec_boolean ("low-bandwidth", "Low bandwidth mode", + "Determines whether we are in low " + "bandwidth mode. This influences " + "polling behaviour.", FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_BLURB); + g_object_class_install_property (object_class, PROP_LOW_BANDWIDTH, param_spec); + param_spec = g_param_spec_string ("stream-server", "The server name used to initialise the stream.", "The server name used when initialising the stream, " "which is usually the part after the @ in the user's JID.", diff --git a/src/gabble-muc-channel.c b/src/gabble-muc-channel.c index 62c100ab..26179d8b 100644 --- a/src/gabble-muc-channel.c +++ b/src/gabble-muc-channel.c @@ -46,6 +46,9 @@ G_DEFINE_TYPE(GabbleMucChannel, gabble_muc_channel, G_TYPE_OBJECT) #define DEFAULT_JOIN_TIMEOUT (180 * 1000) +#define PROPS_POLL_INTERVAL_LOW (60 * 1000 * 5) +#define PROPS_POLL_INTERVAL_HIGH (60 * 1000) + /* * FIXME: move these and the other defines in gabble-media-session.h * to a common header @@ -182,7 +185,7 @@ const RoomPropertySignature room_property_signatures[NUM_ROOM_PROPS] = { }; struct _RoomProperty { - GValue value; + GValue *value; guint flags; }; @@ -206,6 +209,7 @@ struct _GabbleMucChannelPrivate GabbleMucState state; guint join_timer_id; + guint poll_timer_id; TpChannelPasswordFlags password_flags; DBusGMethodInvocation *password_ctx; @@ -250,7 +254,6 @@ gabble_muc_channel_init (GabbleMucChannel *obj) } static void contact_handle_to_room_identity (GabbleMucChannel *chan, GabbleHandle main_handle, GabbleHandle *room_handle, gchar **room_jid); -static void room_properties_init (GabbleMucChannel *chan); static GObject * gabble_muc_channel_constructor (GType type, guint n_props, @@ -296,31 +299,9 @@ gabble_muc_channel_constructor (GType type, guint n_props, /* allow adding ourself */ gabble_group_mixin_change_flags (obj, TP_CHANNEL_GROUP_FLAG_CAN_ADD, 0); - /* initialize room properties */ - room_properties_init (GABBLE_MUC_CHANNEL (obj)); - return obj; } -static void -room_properties_init (GabbleMucChannel *chan) -{ - GabbleMucChannelPrivate *priv; - guint i; - - g_assert (GABBLE_IS_MUC_CHANNEL (chan)); - - priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan); - - for (i = 0; i < NUM_ROOM_PROPS; i++) - { - RoomProperty *prop = &priv->room_props[i]; - - g_value_init (&prop->value, room_property_signatures[i].type); - prop->flags = 0; - } -} - static void room_property_change_value (GabbleMucChannel *chan, guint prop_id, const GValue *new_value, GArray *props); static void room_property_change_flags (GabbleMucChannel *chan, guint prop_id, TpPropertyFlags add, TpPropertyFlags remove, GArray *props); static void room_properties_emit_changed (GabbleMucChannel *chan, GArray *props); @@ -899,6 +880,7 @@ gabble_muc_channel_class_init (GabbleMucChannelClass *gabble_muc_channel_class) } static void clear_join_timer (GabbleMucChannel *chan); +static void clear_poll_timer (GabbleMucChannel *chan); void gabble_muc_channel_dispose (GObject *object) @@ -914,11 +896,30 @@ gabble_muc_channel_dispose (GObject *object) priv->dispose_has_run = TRUE; clear_join_timer (self); + clear_poll_timer (self); if (G_OBJECT_CLASS (gabble_muc_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_muc_channel_parent_class)->dispose (object); } +static void +room_properties_free (GabbleMucChannel *chan) +{ + GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan); + gint i; + + for (i = 0; i < NUM_ROOM_PROPS; i++) + { + RoomProperty *prop = &priv->room_props[i]; + + if (prop->value) + { + g_value_unset (prop->value); + g_free (prop->value); + } + } +} + static void clear_message_queue (GabbleMucChannel *chan); void @@ -931,6 +932,8 @@ gabble_muc_channel_finalize (GObject *object) g_debug (G_STRFUNC); /* free any data held directly by the object here */ + room_properties_free (self); + gabble_handle_unref (handles, TP_HANDLE_TYPE_ROOM, priv->handle); g_free (priv->object_path); @@ -956,6 +959,17 @@ static void clear_join_timer (GabbleMucChannel *chan) } } +static void clear_poll_timer (GabbleMucChannel *chan) +{ + GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan); + + if (priv->poll_timer_id != 0) + { + g_source_remove (priv->poll_timer_id); + priv->poll_timer_id = 0; + } +} + static void change_password_flags (GabbleMucChannel *chan, TpChannelPasswordFlags add, @@ -983,7 +997,8 @@ change_password_flags (GabbleMucChannel *chan, } } -static void provide_password_return_if_pending (GabbleMucChannel *chan, gboolean success) +static void +provide_password_return_if_pending (GabbleMucChannel *chan, gboolean success) { GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan); @@ -1015,6 +1030,18 @@ timeout_join (gpointer data) return FALSE; } +static gboolean +timeout_poll (gpointer data) +{ + GabbleMucChannel *chan = data; + + g_debug ("%s: polling for room properties", G_STRFUNC); + + room_properties_update (chan); + + return TRUE; +} + static void channel_state_changed (GabbleMucChannel *chan, GabbleMucState prev_state, @@ -1032,9 +1059,25 @@ channel_state_changed (GabbleMucChannel *chan, } else if (new_state == MUC_STATE_JOINED) { + gboolean low_bandwidth; + gint interval; + provide_password_return_if_pending (chan, TRUE); clear_join_timer (chan); + + g_object_get (priv->conn, "low-bandwidth", &low_bandwidth, NULL); + + if (low_bandwidth) + interval = PROPS_POLL_INTERVAL_LOW; + else + interval = PROPS_POLL_INTERVAL_HIGH; + + priv->poll_timer_id = g_timeout_add (interval, timeout_poll, chan); + } + else if (new_state == MUC_STATE_ENDED) + { + clear_poll_timer (chan); } } @@ -2435,7 +2478,7 @@ gboolean gabble_muc_channel_get_properties (GabbleMucChannel *obj, const GArray dbus_g_type_struct_set (&val_struct, 0, prop_id, - 1, &priv->room_props[prop_id].value, + 1, priv->room_props[prop_id].value, G_MAXUINT); g_ptr_array_add (*ret, g_value_get_boxed (&val_struct)); @@ -2577,7 +2620,7 @@ gboolean gabble_muc_channel_set_properties (GabbleMucChannel *obj, const GPtrArr /* Compatible type? */ if (!g_value_type_compatible (G_VALUE_TYPE (prop_val), - G_VALUE_TYPE (&priv->room_props[prop_id].value))) + G_VALUE_TYPE (priv->room_props[prop_id].value))) { error = g_error_new (TELEPATHY_ERRORS, NotAvailable, "incompatible value type for property identifier %d", @@ -2951,6 +2994,40 @@ room_property_flags_to_string (TpPropertyFlags flags) return g_string_free (str, FALSE); } +static gboolean +values_are_equal (const GValue *v1, const GValue *v2) +{ + GType type = G_VALUE_TYPE (v1); + const gchar *s1, *s2; + + switch (type) { + case G_TYPE_BOOLEAN: + return (g_value_get_boolean (v1) == g_value_get_boolean (v2)); + + case G_TYPE_STRING: + s1 = g_value_get_string (v1); + s2 = g_value_get_string (v2); + + /* are they both NULL? */ + if (s1 == s2) + return TRUE; + + /* is one of them NULL? */ + if (s1 == NULL || s2 == NULL) + return FALSE; + + return (strcmp (s1, s2) == 0); + + case G_TYPE_UINT: + return (g_value_get_uint (v1) == g_value_get_uint (v2)); + + case G_TYPE_INT: + return (g_value_get_int (v1) == g_value_get_int (v2)); + } + + return FALSE; +} + static void room_property_change_value (GabbleMucChannel *chan, guint prop_id, @@ -2958,18 +3035,37 @@ room_property_change_value (GabbleMucChannel *chan, GArray *props) { GabbleMucChannelPrivate *priv; - GValue *cur_val; + RoomProperty *prop; g_assert (GABBLE_IS_MUC_CHANNEL (chan)); priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan); - cur_val = &priv->room_props[prop_id].value; + prop = &priv->room_props[prop_id]; + + if (prop->value) + { + if (values_are_equal (prop->value, new_value)) + return; + } + else + { + prop->value = g_new0 (GValue, 1); + g_value_init (prop->value, room_property_signatures[prop_id].type); + } - g_value_copy (new_value, cur_val); + g_value_copy (new_value, prop->value); if (props) { + gint i; + + for (i = 0; i < props->len; i++) + { + if (g_array_index (props, guint, i) == prop_id) + return; + } + g_array_append_val (props, prop_id); } else @@ -2993,6 +3089,7 @@ room_property_change_flags (GabbleMucChannel *chan, { GabbleMucChannelPrivate *priv; RoomProperty *prop; + guint prev_flags; g_assert (GABBLE_IS_MUC_CHANNEL (chan)); @@ -3000,13 +3097,26 @@ room_property_change_flags (GabbleMucChannel *chan, prop = &priv->room_props[prop_id]; + prev_flags = prop->flags; + prop->flags |= add; prop->flags &= ~remove; + if (prop->flags == prev_flags) + return; + if (add != 0 || remove != 0) { if (props) { + gint i; + + for (i = 0; i < props->len; i++) + { + if (g_array_index (props, guint, i) == prop_id) + return; + } + g_array_append_val (props, prop_id); } else @@ -3034,6 +3144,9 @@ room_properties_emit_changed (GabbleMucChannel *chan, GArray *props) priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan); + if (props->len == 0) + return; + prop_arr = g_ptr_array_sized_new (props->len); printf (ANSI_BOLD_ON ANSI_FG_CYAN @@ -3051,7 +3164,7 @@ room_properties_emit_changed (GabbleMucChannel *chan, GArray *props) dbus_g_type_struct_set (&prop_val, 0, prop_id, - 1, &priv->room_props[prop_id].value, + 1, priv->room_props[prop_id].value, G_MAXUINT); g_ptr_array_add (prop_arr, g_value_get_boxed (&prop_val)); @@ -3081,6 +3194,9 @@ room_properties_emit_flags (GabbleMucChannel *chan, GArray *props) priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan); + if (props->len == 0) + return; + prop_arr = g_ptr_array_sized_new (props->len); printf (ANSI_BOLD_ON ANSI_FG_WHITE |