diff options
-rw-r--r-- | NEWS | 53 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/im-channel.c | 1 | ||||
-rw-r--r-- | src/im-factory.c | 12 | ||||
-rw-r--r-- | src/media-channel.c | 1 | ||||
-rw-r--r-- | src/media-factory.c | 30 | ||||
-rw-r--r-- | src/media-stream.c | 47 | ||||
-rw-r--r-- | src/muc-channel.c | 1 | ||||
-rw-r--r-- | src/muc-factory.c | 7 | ||||
-rw-r--r-- | src/olpc-activity-view.c | 6 | ||||
-rw-r--r-- | src/olpc-activity.c | 24 | ||||
-rw-r--r-- | src/olpc-buddy-view.c | 6 | ||||
-rw-r--r-- | src/olpc-gadget-manager.c | 12 | ||||
-rw-r--r-- | src/olpc-view.c | 30 | ||||
-rw-r--r-- | src/private-tubes-factory.c | 11 | ||||
-rw-r--r-- | src/roomlist-channel.c | 1 | ||||
-rw-r--r-- | src/roomlist-manager.c | 6 | ||||
-rw-r--r-- | src/roster-channel.c | 1 | ||||
-rw-r--r-- | src/tube-dbus.c | 32 | ||||
-rw-r--r-- | src/tube-iface.c | 51 | ||||
-rw-r--r-- | src/tube-stream.c | 298 | ||||
-rw-r--r-- | src/tubes-channel.c | 33 | ||||
-rw-r--r-- | tests/twisted/Makefile.am | 1 | ||||
-rw-r--r-- | tests/twisted/roster/ensure.py | 14 | ||||
-rw-r--r-- | tests/twisted/tools/tmp-session-bus.conf.in | 2 | ||||
-rw-r--r-- | tests/twisted/tubes/test-si-accept-tubes.py | 269 | ||||
-rw-r--r-- | tests/twisted/tubes/test-si-tubes.py | 69 | ||||
-rw-r--r-- | tools/glib-ginterface-gen.py | 15 | ||||
-rw-r--r-- | tools/telepathy.am | 7 |
29 files changed, 678 insertions, 364 deletions
@@ -1,3 +1,56 @@ +telepathy-gabble 0.7.16 (UNRELEASED) +==================================== + +Dependencies: + +Enhancements: + +Fixes: + +telepathy-gabble 0.7.15 (2008-11-06) +==================================== + +The "brunch and fireworks" release. + +Enhancements: + +* fd.o #17770: remove some redundant handle validation from channel managers + +* Add the immutable Interfaces property to all NewChannels signals and + CreateChannel/EnsureChannel results + +Fixes: + +* Spec compliance: don't advertise StreamedMedia channels with handle type + NONE as requestable (they can be created, but not with CreateChannel or + EnsureChannel, so they shouldn't be in RequestableChannelClasses) + +* Ignore candidates > 1 in Jingle rather than rejecting them, for + compatibility with Farsight 2 (in which RTCP produces a second candidate) + +telepathy-gabble 0.7.14 (2008-11-04) +==================================== + +The "exterminate, annihilate, destroy" release. + +Dependencies: + +* telepathy-glib 0.7.18 + +Enhancements: + +* Comply with specification 0.17.14 + * depend on telepathy-glib 0.7.18 + * implement the Destroyable interface on IM channels + * set the RESCUED flag on messages in respawned IM channels + * set the SCROLLBACK flag on discussion history in MUC channels + +* Start to implement the new Tubes API draft (one Channel per Tube) + +Fixes: + +* fd.o #16797: Don't send the close message for Tubes twice + telepathy-gabble 0.7.13 (2008-10-28) ==================================== diff --git a/configure.ac b/configure.ac index 3548ab33d..b9ee401d1 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,7 @@ AC_PREREQ([2.59]) m4_define([gabble_major_version], [0]) m4_define([gabble_minor_version], [7]) -m4_define([gabble_micro_version], [13]) +m4_define([gabble_micro_version], [15]) m4_define([gabble_nano_version], [1]) # Some magic diff --git a/src/im-channel.c b/src/im-channel.c index 95ee6d79f..79ea68cd2 100644 --- a/src/im-channel.c +++ b/src/im-channel.c @@ -240,6 +240,7 @@ gabble_im_channel_get_property (GObject *object, TP_IFACE_CHANNEL, "InitiatorHandle", TP_IFACE_CHANNEL, "InitiatorID", TP_IFACE_CHANNEL, "Requested", + TP_IFACE_CHANNEL, "Interfaces", NULL)); break; default: diff --git a/src/im-factory.c b/src/im-factory.c index fb762e17f..e81e5b61e 100644 --- a/src/im-factory.c +++ b/src/im-factory.c @@ -304,11 +304,6 @@ im_channel_closed_cb (GabbleIMChannel *chan, gpointer user_data) DEBUG ("%p, channel %p", self, chan); - g_object_get (chan, - "handle", &contact_handle, - "channel-destroyed", &really_destroyed, - NULL); - tp_channel_manager_emit_channel_closed_for_object (self, (TpExportableChannel *) chan); @@ -520,8 +515,6 @@ gabble_im_factory_requestotron (GabbleImFactory *self, gboolean require_new) { TpBaseConnection *base_conn = (TpBaseConnection *) self->priv->conn; - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - base_conn, TP_HANDLE_TYPE_CONTACT); TpHandle handle; GError *error = NULL; TpExportableChannel *channel; @@ -534,11 +527,10 @@ gabble_im_factory_requestotron (GabbleImFactory *self, TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT) return FALSE; + /* validity already checked by TpBaseConnection */ handle = tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandle", NULL); - - if (!tp_handle_is_valid (contact_repo, handle, &error)) - goto error; + g_assert (handle != 0); if (tp_channel_manager_asv_has_unknown_properties (request_properties, im_channel_fixed_properties, im_channel_allowed_properties, diff --git a/src/media-channel.c b/src/media-channel.c index eb0f1707b..de5b0e471 100644 --- a/src/media-channel.c +++ b/src/media-channel.c @@ -483,6 +483,7 @@ gabble_media_channel_get_property (GObject *object, TP_IFACE_CHANNEL, "InitiatorHandle", TP_IFACE_CHANNEL, "InitiatorID", TP_IFACE_CHANNEL, "Requested", + TP_IFACE_CHANNEL, "Interfaces", NULL)); break; default: diff --git a/src/media-factory.c b/src/media-factory.c index 188cff4e9..3dfba68be 100644 --- a/src/media-factory.c +++ b/src/media-factory.c @@ -845,6 +845,8 @@ static const gchar * const named_channel_allowed_properties[] = { NULL }; +/* not advertised in foreach_channel_class - can only be requested with + * RequestChannel, not with CreateChannel/EnsureChannel */ static const gchar * const anon_channel_allowed_properties[] = { NULL }; @@ -857,21 +859,16 @@ gabble_media_factory_foreach_channel_class (TpChannelManager *manager, { GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); - GValue *value, *handle_type_value; + GValue *value; value = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA); g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType", value); - handle_type_value = tp_g_value_slice_new (G_TYPE_UINT); - /* no uint value yet - we'll change it for each channel class */ - g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType", - handle_type_value); + value = tp_g_value_slice_new (G_TYPE_UINT); + g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); + g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType", value); - g_value_set_uint (handle_type_value, TP_HANDLE_TYPE_NONE); - func (manager, table, anon_channel_allowed_properties, user_data); - - g_value_set_uint (handle_type_value, TP_HANDLE_TYPE_CONTACT); func (manager, table, named_channel_allowed_properties, user_data); g_hash_table_destroy (table); @@ -949,13 +946,8 @@ gabble_media_factory_requestotron (TpChannelManager *manager, switch (handle_type) { case TP_HANDLE_TYPE_NONE: - if (handle != 0) - { - g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "TargetHandle must be zero or omitted if TargetHandleType is " - "NONE"); - goto error; - } + /* already checked by TpBaseConnection */ + g_assert (handle == 0); if (require_target_handle) { @@ -974,10 +966,8 @@ gabble_media_factory_requestotron (TpChannelManager *manager, break; case TP_HANDLE_TYPE_CONTACT: - if (!tp_handle_is_valid ( - tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT), - handle, &error)) - goto error; + /* validity already checked by TpBaseConnection */ + g_assert (handle != 0); if (tp_channel_manager_asv_has_unknown_properties (request_properties, media_channel_fixed_properties, named_channel_allowed_properties, diff --git a/src/media-stream.c b/src/media-stream.c index 60cadf701..722310af3 100644 --- a/src/media-stream.c +++ b/src/media-stream.c @@ -795,6 +795,7 @@ gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface, guint component_id; const gchar *addr; GType candidate_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE; + guint i; g_assert (GABBLE_IS_MEDIA_STREAM (self)); @@ -822,9 +823,9 @@ gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface, 1, transports, G_MAXUINT); - if (transports->len != 1) + if (transports->len < 1) { - GError only_one = { TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "google p2p " + GError only_one = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "google p2p " "connections only support the concept of one transport per " "candidate" }; GMS_DEBUG_WARNING (priv->session, "%s: number of transports was not 1; " @@ -833,7 +834,45 @@ gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface, return; } - transport = g_ptr_array_index (transports, 0); + if (transports->len > 1) + { + GMS_DEBUG_WARNING (priv->session, "google p2p " + "connections only support the concept of one transport per " + "candidate, ignoring other components"); + } + + for (i = 0; i < transports->len; i++) + { + guint component; + + transport = g_ptr_array_index (transports, i); + component = g_value_get_uint (g_value_array_get_nth (transport, 0)); + + /* Accept component 0 because old farsight1 stream-engine didn't set the + * component + */ + if (component == 0 || component == 1) + { + break; + } + else + { + transport = NULL; + } + } + + + if (transport == NULL) + { + GError only_one = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "You need" + " at least a component 1." }; + GMS_DEBUG_WARNING (priv->session, "%s: number of transports was not 1; " + "rejecting", G_STRFUNC); + dbus_g_method_return_error (context, &only_one); + return; + } + + addr = g_value_get_string (g_value_array_get_nth (transport, 1)); if (!strcmp (addr, "127.0.0.1")) { @@ -1021,7 +1060,7 @@ _add_rtp_candidate_node (GabbleMediaSession *session, LmMessageNode *parent, transports = g_value_get_boxed (g_value_array_get_nth (candidate, 1)); /* jingle audio only supports the concept of one transport per candidate */ - g_assert (transports->len == 1); + g_assert (transports->len >= 1); g_value_init (&transport, TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT); g_value_set_static_boxed (&transport, g_ptr_array_index (transports, 0)); diff --git a/src/muc-channel.c b/src/muc-channel.c index c74bbff73..7c7e21e75 100644 --- a/src/muc-channel.c +++ b/src/muc-channel.c @@ -868,6 +868,7 @@ gabble_muc_channel_get_property (GObject *object, TP_IFACE_CHANNEL, "InitiatorHandle", TP_IFACE_CHANNEL, "InitiatorID", TP_IFACE_CHANNEL, "Requested", + TP_IFACE_CHANNEL, "Interfaces", NULL)); break; default: diff --git a/src/muc-factory.c b/src/muc-factory.c index 540c127c6..4509a1e09 100644 --- a/src/muc-factory.c +++ b/src/muc-factory.c @@ -1303,8 +1303,6 @@ gabble_muc_factory_request (GabbleMucFactory *self, { GabbleMucFactoryPrivate *priv = GABBLE_MUC_FACTORY_GET_PRIVATE (self); TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn; - TpHandleRepoIface *room_repo = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_ROOM); GError *error = NULL; TpHandle handle; const gchar *channel_type; @@ -1315,11 +1313,10 @@ gabble_muc_factory_request (GabbleMucFactory *self, TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_ROOM) return FALSE; + /* validity already checked by TpBaseConnection */ handle = tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandle", NULL); - - if (!tp_handle_is_valid (room_repo, handle, &error)) - goto error; + g_assert (handle != 0); channel_type = tp_asv_get_string (request_properties, TP_IFACE_CHANNEL ".ChannelType"); diff --git a/src/olpc-activity-view.c b/src/olpc-activity-view.c index 6d2959922..c26607650 100644 --- a/src/olpc-activity-view.c +++ b/src/olpc-activity-view.c @@ -421,8 +421,7 @@ gabble_olpc_activity_view_class_init ( "View's search properties", "The activity properties Gadget should look for", TP_HASH_TYPE_STRING_VARIANT_MAP, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_VIEW_PROPERTIES, param_spec); @@ -430,8 +429,7 @@ gabble_olpc_activity_view_class_init ( "View's search participants", "The activity participants Gadget should look for", GABBLE_ARRAY_TYPE_HANDLE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PARTICIPANTS, param_spec); diff --git a/src/olpc-activity.c b/src/olpc-activity.c index 3a15cb12c..5d72f7d74 100644 --- a/src/olpc-activity.c +++ b/src/olpc-activity.c @@ -220,11 +220,7 @@ gabble_olpc_activity_class_init ( "GabbleConnection object", "Gabble connection object that owns this activity object.", GABBLE_TYPE_CONNECTION, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); param_spec = g_param_spec_uint ( @@ -232,11 +228,7 @@ gabble_olpc_activity_class_init ( "activity room", "a TpHandle representing the activity room", 0, G_MAXUINT, 0, - G_PARAM_CONSTRUCT | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ROOM, param_spec); param_spec = g_param_spec_string ( @@ -244,11 +236,7 @@ gabble_olpc_activity_class_init ( "activity id", "the activity ID", NULL, - G_PARAM_CONSTRUCT | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ID, param_spec); param_spec = g_param_spec_boxed ( @@ -256,11 +244,7 @@ gabble_olpc_activity_class_init ( "activity properties", "a GHashTable containing activity's properties", G_TYPE_HASH_TABLE, - G_PARAM_CONSTRUCT | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PROPERTIES, param_spec); } diff --git a/src/olpc-buddy-view.c b/src/olpc-buddy-view.c index 60e0adc31..e5e93d90c 100644 --- a/src/olpc-buddy-view.c +++ b/src/olpc-buddy-view.c @@ -363,16 +363,14 @@ gabble_olpc_buddy_view_class_init ( "View's search properties", "The buddy properties Gadget should look for", TP_HASH_TYPE_STRING_VARIANT_MAP, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_VIEW_PROPERTIES, param_spec); param_spec = g_param_spec_string ("alias", "View's search alias", "The buddy alias Gadget should look for", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ALIAS, param_spec); diff --git a/src/olpc-gadget-manager.c b/src/olpc-gadget-manager.c index db3f036f4..166582582 100644 --- a/src/olpc-gadget-manager.c +++ b/src/olpc-gadget-manager.c @@ -292,10 +292,8 @@ create_buddy_view_channel (GabbleOlpcGadgetManager *self, return NULL; } - if ((tp_asv_get_uint32 (request_properties, - TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0) || - (tp_asv_get_uint32 (request_properties, - TP_IFACE_CHANNEL ".TargetHandle", NULL) != 0)) + if (tp_asv_get_uint32 (request_properties, + TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0) { g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "Views channels can't have a target handle"); @@ -364,10 +362,8 @@ create_activity_view_channel (GabbleOlpcGadgetManager *self, return NULL; } - if ((tp_asv_get_uint32 (request_properties, - TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0) || - (tp_asv_get_uint32 (request_properties, - TP_IFACE_CHANNEL ".TargetHandle", NULL) != 0)) + if (tp_asv_get_uint32 (request_properties, + TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0) { g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "Views channels can't have a target handle"); diff --git a/src/olpc-view.c b/src/olpc-view.c index db9eb417a..5d0d24e58 100644 --- a/src/olpc-view.c +++ b/src/olpc-view.c @@ -413,37 +413,32 @@ gabble_olpc_view_class_init (GabbleOlpcViewClass *gabble_olpc_view_class) param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces", "Additional Channel.Interface.* interfaces", G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); param_spec = g_param_spec_string ("target-id", "Peer's bare JID", "The string obtained by inspecting the peer handle (never the full JID)", NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec); param_spec = g_param_spec_boolean ("requested", "Requested?", "True if this channel was requested by the local user", FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_REQUESTED, param_spec); param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle", "The contact who initiated the channel", 0, G_MAXUINT32, 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE, param_spec); param_spec = g_param_spec_string ("initiator-id", "Initiator's bare JID", "The string obtained by inspecting the initiator-handle", NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIATOR_ID, param_spec); @@ -451,39 +446,34 @@ gabble_olpc_view_class_init (GabbleOlpcViewClass *gabble_olpc_view_class) "The maximum number of elements that Gadget has to return to the " "search request.", 0, G_MAXUINT32, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_MAX_SIZE, param_spec); param_spec = g_param_spec_boxed ("buddies", "View's buddies", "The contact handles of the buddies who are in this view channel", GABBLE_ARRAY_TYPE_HANDLE, - G_PARAM_READABLE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_BUDDIES, param_spec); param_spec = g_param_spec_boxed ("activities", "View's activities", "The activities which are in this view channel", GABBLE_ARRAY_TYPE_ACTIVITY_LIST, - G_PARAM_READABLE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ACTIVITIES, param_spec); param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this view object.", GABBLE_TYPE_CONNECTION, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); param_spec = g_param_spec_uint ("id", "query ID", "The ID of the query associated with this view", 0, G_MAXUINT, 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ID, param_spec); signals[BUDDY_ACTIVITIES_CHANGED] = diff --git a/src/private-tubes-factory.c b/src/private-tubes-factory.c index de49d3aba..7ad7f6054 100644 --- a/src/private-tubes-factory.c +++ b/src/private-tubes-factory.c @@ -623,8 +623,6 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self, gboolean require_new) { TpBaseConnection *base_conn = (TpBaseConnection *) self->priv->conn; - TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - base_conn, TP_HANDLE_TYPE_CONTACT); TpHandle handle; GError *error = NULL; GabbleTubesChannel *channel; @@ -693,11 +691,10 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self, } } + /* validity already checked by TpBaseConnection */ handle = tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandle", NULL); - - if (!tp_handle_is_valid (contact_repo, handle, &error)) - goto error; + g_assert (handle != 0); /* Don't support opening a channel to our self handle */ if (handle == base_conn->self_handle) @@ -722,8 +719,8 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self, if (require_new) { g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE, - "Already chatting with contact #%u in another channel", handle); - DEBUG ("Already chatting with contact #%u in another channel", + "Tubes channel with contact #%u already exists", handle); + DEBUG ("Tubes channel with contact #%u already exists", handle); goto error; } diff --git a/src/roomlist-channel.c b/src/roomlist-channel.c index 94dfe429d..84a796775 100644 --- a/src/roomlist-channel.c +++ b/src/roomlist-channel.c @@ -199,6 +199,7 @@ gabble_roomlist_channel_get_property (GObject *object, TP_IFACE_CHANNEL, "InitiatorHandle", TP_IFACE_CHANNEL, "InitiatorID", TP_IFACE_CHANNEL, "Requested", + TP_IFACE_CHANNEL, "Interfaces", TP_IFACE_CHANNEL_TYPE_ROOM_LIST, "Server", NULL)); break; diff --git a/src/roomlist-manager.c b/src/roomlist-manager.c index e16627a0d..2faa48a83 100644 --- a/src/roomlist-manager.c +++ b/src/roomlist-manager.c @@ -325,10 +325,8 @@ gabble_roomlist_manager_handle_request (TpChannelManager *manager, TP_IFACE_CHANNEL_TYPE_ROOM_LIST)) return FALSE; - if ((tp_asv_get_uint32 (request_properties, - TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0) || - (tp_asv_get_uint32 (request_properties, - TP_IFACE_CHANNEL ".TargetHandle", NULL) != 0)) + if (tp_asv_get_uint32 (request_properties, + TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0) { g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, "RoomList channels can't have a target handle"); diff --git a/src/roster-channel.c b/src/roster-channel.c index 87a69bcbf..3ff304a05 100644 --- a/src/roster-channel.c +++ b/src/roster-channel.c @@ -252,6 +252,7 @@ gabble_roster_channel_get_property (GObject *object, TP_IFACE_CHANNEL, "InitiatorHandle", TP_IFACE_CHANNEL, "InitiatorID", TP_IFACE_CHANNEL, "Requested", + TP_IFACE_CHANNEL, "Interfaces", NULL)); break; default: diff --git a/src/tube-dbus.c b/src/tube-dbus.c index 85720d76b..be8c7b1c2 100644 --- a/src/tube-dbus.c +++ b/src/tube-dbus.c @@ -791,11 +791,7 @@ gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class) "Initiator handle", "The TpHandle of the initiator of this tube object.", 0, G_MAXUINT32, 0, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE, param_spec); @@ -805,10 +801,7 @@ gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class) "Bytestream object used for streaming data for this" "tube object.", G_TYPE_OBJECT, - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_BYTESTREAM, param_spec); @@ -817,11 +810,7 @@ gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class) "stream id", "The identifier of this tube's bytestream", "", - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STREAM_ID, param_spec); @@ -830,10 +819,7 @@ gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class) "D-Bus address", "The D-Bus address on which this tube will listen for connections", "", - G_PARAM_READABLE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DBUS_ADDRESS, param_spec); @@ -842,10 +828,7 @@ gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class) "D-Bus name", "The local D-Bus name on the virtual bus (used for muc tubes only).", "", - G_PARAM_READABLE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DBUS_NAME, param_spec); param_spec = g_param_spec_boxed ( @@ -853,10 +836,7 @@ gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class) "D-Bus names", "Mapping of contact handles to D-Bus names (used for muc tubes only).", G_TYPE_HASH_TABLE, - G_PARAM_READABLE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DBUS_NAMES, param_spec); signals[OPENED] = diff --git a/src/tube-iface.c b/src/tube-iface.c index 3aa5a71c2..0a819d0db 100644 --- a/src/tube-iface.c +++ b/src/tube-iface.c @@ -68,11 +68,7 @@ gabble_tube_iface_base_init (gpointer klass) "GabbleConnection object", "Gabble connection object that owns this tube object.", GABBLE_TYPE_CONNECTION, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( @@ -81,11 +77,7 @@ gabble_tube_iface_base_init (gpointer klass) "The TpHandle associated with the tubes channel that" "owns this tube object.", 0, G_MAXUINT32, 0, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( @@ -94,11 +86,7 @@ gabble_tube_iface_base_init (gpointer klass) "The TpHandleType of the handle associated with the tubes channel" "that owns this tube object.", 0, G_MAXUINT32, 0, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( @@ -107,11 +95,7 @@ gabble_tube_iface_base_init (gpointer klass) "The handle to use for ourself. This can be different from the " "connection's self handle if our handle is a room handle.", 0, G_MAXUINT, 0, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( @@ -119,11 +103,7 @@ gabble_tube_iface_base_init (gpointer klass) "id", "The unique identifier of this tube", 0, G_MAXUINT32, 0, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( @@ -131,10 +111,7 @@ gabble_tube_iface_base_init (gpointer klass) "Tube type", "The TpTubeType this tube object.", 0, G_MAXUINT32, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_string ( @@ -142,11 +119,7 @@ gabble_tube_iface_base_init (gpointer klass) "service name", "the service associated with this tube object.", "", - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_boxed ( @@ -154,10 +127,7 @@ gabble_tube_iface_base_init (gpointer klass) "parameters GHashTable", "GHashTable containing parameters of this tube object.", TP_HASH_TYPE_STRING_VARIANT_MAP, - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( @@ -165,10 +135,7 @@ gabble_tube_iface_base_init (gpointer klass) "Tube state", "The GabbleTubeState of this tube object", 0, G_MAXUINT32, TP_TUBE_STATE_REMOTE_PENDING, - G_PARAM_READABLE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); initialized = TRUE; diff --git a/src/tube-stream.c b/src/tube-stream.c index 84230a3c4..37e4b5a0a 100644 --- a/src/tube-stream.c +++ b/src/tube-stream.c @@ -1053,6 +1053,7 @@ gabble_tube_stream_get_property (GObject *object, TP_IFACE_CHANNEL, "InitiatorHandle", TP_IFACE_CHANNEL, "InitiatorID", TP_IFACE_CHANNEL, "Requested", + TP_IFACE_CHANNEL, "Interfaces", NULL)); break; case PROP_REQUESTED: @@ -1148,9 +1149,6 @@ gabble_tube_stream_set_property (GObject *object, } break; case PROP_ACCESS_CONTROL: - /* For now, only "localhost" control is implemented */ - g_assert (g_value_get_uint (value) == - TP_SOCKET_ACCESS_CONTROL_LOCALHOST); priv->access_control = g_value_get_uint (value); break; case PROP_ACCESS_CONTROL_PARAM: @@ -1336,8 +1334,7 @@ gabble_tube_stream_class_init (GabbleTubeStreamClass *gabble_tube_stream_class) "Supported socket types", "GHashTable containing supported socket types.", dbus_g_type_get_map ("GHashTable", G_TYPE_UINT, DBUS_TYPE_G_UINT_ARRAY), - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SUPPORTED_SOCKET_TYPES, param_spec); @@ -1348,10 +1345,7 @@ gabble_tube_stream_class_init (GabbleTubeStreamClass *gabble_tube_stream_class) "address of the local service", 0, NUM_TP_SOCKET_ADDRESS_TYPES - 1, TP_SOCKET_ADDRESS_TYPE_UNIX, - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ADDRESS_TYPE, param_spec); @@ -1360,10 +1354,7 @@ gabble_tube_stream_class_init (GabbleTubeStreamClass *gabble_tube_stream_class) "address", "The listening address of the local service, as indicated by the " "address-type", - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ADDRESS, param_spec); param_spec = g_param_spec_uint ( @@ -1373,10 +1364,7 @@ gabble_tube_stream_class_init (GabbleTubeStreamClass *gabble_tube_stream_class) "the local service applies to the local socket", 0, NUM_TP_SOCKET_ACCESS_CONTROLS - 1, TP_SOCKET_ACCESS_CONTROL_LOCALHOST, - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ACCESS_CONTROL, param_spec); @@ -1385,10 +1373,7 @@ gabble_tube_stream_class_init (GabbleTubeStreamClass *gabble_tube_stream_class) "access control param", "A parameter for the access control type, to be interpreted as specified" "in the documentation for the Socket_Access_Control enum.", - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ACCESS_CONTROL_PARAM, param_spec); @@ -1401,31 +1386,27 @@ gabble_tube_stream_class_init (GabbleTubeStreamClass *gabble_tube_stream_class) param_spec = g_param_spec_string ("target-id", "Target JID", "The string obtained by inspecting the target handle", NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec); param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle", "The contact who initiated the channel", 0, G_MAXUINT32, 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE, param_spec); param_spec = g_param_spec_string ("initiator-id", "Initiator's bare JID", "The string obtained by inspecting the initiator-handle", NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIATOR_ID, param_spec); param_spec = g_param_spec_boolean ("requested", "Requested?", "True if this channel was requested by the local user", FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_REQUESTED, param_spec); signals[OPENED] = @@ -1544,13 +1525,23 @@ gabble_tube_stream_accept (GabbleTubeIface *tube, GabbleTubeStream *self = GABBLE_TUBE_STREAM (tube); GabbleTubeStreamPrivate *priv = GABBLE_TUBE_STREAM_GET_PRIVATE (self); + if (!gabble_tube_stream_check_params (priv->address_type, NULL, + priv->access_control, priv->access_control_param, error)) + { + goto fail; + } + if (priv->state != GABBLE_TUBE_CHANNEL_STATE_LOCAL_PENDING) - return TRUE; + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "Tube is not in the local pending state"); + goto fail; + } if (!tube_stream_open (self, error)) { gabble_tube_iface_close (GABBLE_TUBE_IFACE (self), TRUE); - return FALSE; + goto fail; } priv->state = GABBLE_TUBE_CHANNEL_STATE_OPEN; @@ -1561,6 +1552,13 @@ gabble_tube_stream_accept (GabbleTubeIface *tube, g_signal_emit (G_OBJECT (self), signals[OPENED], 0); return TRUE; + +fail: + priv->address_type = 0; + priv->access_control = 0; + tp_g_value_slice_free (priv->access_control_param); + priv->access_control_param = NULL; + return FALSE; } /** @@ -1700,57 +1698,60 @@ check_unix_params (TpSocketAddressType address_type, g_assert (address_type == TP_SOCKET_ADDRESS_TYPE_UNIX); /* Check address type */ - if (G_VALUE_TYPE (address) != DBUS_TYPE_G_UCHAR_ARRAY) + if (address != NULL) { - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "Unix socket address is supposed to be ay"); - return FALSE; - } + if (G_VALUE_TYPE (address) != DBUS_TYPE_G_UCHAR_ARRAY) + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "Unix socket address is supposed to be ay"); + return FALSE; + } - array = g_value_get_boxed (address); + array = g_value_get_boxed (address); - if (array->len > sizeof (dummy.sun_path) - 1) - { - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "Unix socket path is too long (max length allowed: %" - G_GSIZE_FORMAT ")", - sizeof (dummy.sun_path) - 1); - return FALSE; - } - - for (i = 0; i < array->len; i++) - { - if (g_array_index (array, gchar , i) == '\0') + if (array->len > sizeof (dummy.sun_path) - 1) { g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "Unix socket path can't contain zero bytes"); + "Unix socket path is too long (max length allowed: %" + G_GSIZE_FORMAT ")", + sizeof (dummy.sun_path) - 1); return FALSE; } - } - socket_address = g_string_new_len (array->data, array->len); + for (i = 0; i < array->len; i++) + { + if (g_array_index (array, gchar , i) == '\0') + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "Unix socket path can't contain zero bytes"); + return FALSE; + } + } - if (g_stat (socket_address->str, &stat_buff) == -1) - { - DEBUG ("Error calling stat on socket: %s", g_strerror (errno)); + socket_address = g_string_new_len (array->data, array->len); - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "%s: %s", - socket_address->str, g_strerror (errno)); - g_string_free (socket_address, TRUE); - return FALSE; - } + if (g_stat (socket_address->str, &stat_buff) == -1) + { + DEBUG ("Error calling stat on socket: %s", g_strerror (errno)); - if (!S_ISSOCK (stat_buff.st_mode)) - { - DEBUG ("%s is not a socket", socket_address->str); + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, "%s: %s", + socket_address->str, g_strerror (errno)); + g_string_free (socket_address, TRUE); + return FALSE; + } - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "%s is not a socket", socket_address->str); - g_string_free (socket_address, TRUE); - return FALSE; - } + if (!S_ISSOCK (stat_buff.st_mode)) + { + DEBUG ("%s is not a socket", socket_address->str); - g_string_free (socket_address, TRUE); + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "%s is not a socket", socket_address->str); + g_string_free (socket_address, TRUE); + return FALSE; + } + + g_string_free (socket_address, TRUE); + } if (access_control != TP_SOCKET_ACCESS_CONTROL_LOCALHOST) { @@ -1770,62 +1771,65 @@ check_ip_params (TpSocketAddressType address_type, const GValue *access_control_param, GError **error) { - gchar *ip; - guint port; - struct addrinfo req, *result = NULL; - int ret; - /* Check address type */ - if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) + if (address != NULL) { - if (G_VALUE_TYPE (address) != TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4) + gchar *ip; + guint port; + struct addrinfo req, *result = NULL; + int ret; + + if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) { - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "IPv4 socket address is supposed to be sq"); - return FALSE; + if (G_VALUE_TYPE (address) != TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4) + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "IPv4 socket address is supposed to be sq"); + return FALSE; + } } - } - else if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV6) - { - if (G_VALUE_TYPE (address) != TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV6) + else if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV6) { - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "IPv6 socket address is supposed to be sq"); - return FALSE; + if (G_VALUE_TYPE (address) != TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV6) + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "IPv6 socket address is supposed to be sq"); + return FALSE; + } + } + else + { + g_return_val_if_reached (FALSE); } - } - else - { - g_return_val_if_reached (FALSE); - } - dbus_g_type_struct_get (address, - 0, &ip, - 1, &port, - G_MAXUINT); + dbus_g_type_struct_get (address, + 0, &ip, + 1, &port, + G_MAXUINT); - memset (&req, 0, sizeof (req)); - req.ai_flags = AI_NUMERICHOST; - req.ai_socktype = SOCK_STREAM; - req.ai_protocol = IPPROTO_TCP; + memset (&req, 0, sizeof (req)); + req.ai_flags = AI_NUMERICHOST; + req.ai_socktype = SOCK_STREAM; + req.ai_protocol = IPPROTO_TCP; - if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) - req.ai_family = AF_INET; - else - req.ai_family = AF_INET6; + if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) + req.ai_family = AF_INET; + else + req.ai_family = AF_INET6; + + ret = getaddrinfo (ip, NULL, &req, &result); + if (ret != 0) + { + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "Invalid address: %s", gai_strerror (ret)); + g_free (ip); + return FALSE; + } - ret = getaddrinfo (ip, NULL, &req, &result); - if (ret != 0) - { - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "Invalid address: %s", gai_strerror (ret)); g_free (ip); - return FALSE; + freeaddrinfo (result); } - g_free (ip); - freeaddrinfo (result); - if (access_control != TP_SOCKET_ACCESS_CONTROL_LOCALHOST) { g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, @@ -1837,6 +1841,10 @@ check_ip_params (TpSocketAddressType address_type, return TRUE; } +/* used to check access control parameters both for OfferStreamTube and + * AcceptStreamTube. In case of AcceptStreamTube, address is NULL because we + * listen on the socket after the parameters have been accepted + */ gboolean gabble_tube_stream_check_params (TpSocketAddressType address_type, const GValue *address, @@ -1876,6 +1884,9 @@ gabble_tube_stream_offer (GabbleTubeStream *self, TpHandleRepoIface *contact_repo; const gchar *jid; gboolean result; + GabblePresence *presence; + const gchar *resource; + gchar *full_jid; g_assert (priv->state == GABBLE_TUBE_CHANNEL_STATE_NOT_OFFERED); @@ -1884,7 +1895,33 @@ gabble_tube_stream_offer (GabbleTubeStream *self, jid = tp_handle_inspect (contact_repo, priv->handle); - msg = lm_message_build (jid, LM_MESSAGE_TYPE_MESSAGE, + presence = gabble_presence_cache_get (priv->conn->presence_cache, + priv->handle); + if (presence == NULL) + { + DEBUG ("can't find tube recipient's presence"); + if (error != NULL) + g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE, + "can't find tube recipient's presence"); + + return FALSE; + } + + resource = gabble_presence_pick_resource_by_caps (presence, + PRESENCE_CAP_SI_TUBES); + if (resource == NULL) + { + DEBUG ("tube recipient doesn't have tubes capabilities"); + if (error != NULL) + g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE, + "tube recipient doesn't have tubes capabilities"); + + return FALSE; + } + + full_jid = g_strdup_printf ("%s/%s", jid, resource); + + msg = lm_message_build (full_jid, LM_MESSAGE_TYPE_MESSAGE, '(', "tube", "", '*', &tube_node, '@', "xmlns", NS_TUBES, @@ -1903,6 +1940,7 @@ gabble_tube_stream_offer (GabbleTubeStream *self, ')', ')', NULL); + g_free (full_jid); g_assert (tube_node != NULL); @@ -2070,39 +2108,13 @@ gabble_tube_stream_accept_stream_tube (GabbleSvcChannelTypeStreamTube *iface, GabbleTubeStreamPrivate *priv = GABBLE_TUBE_STREAM_GET_PRIVATE (self); GError *error = NULL; - if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX) - { - error = g_error_new (TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, - "Address type %d not implemented", address_type); - - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - if (access_control != TP_SOCKET_ACCESS_CONTROL_LOCALHOST) - { - GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "Only the Localhost access control method is implemented" - " by Gabble" }; - - dbus_g_method_return_error (context, &e); - return; - } - + /* parameters sanity checks are done in gabble_tube_stream_accept */ + priv->address_type = address_type; priv->access_control = access_control; - g_assert (priv->access_control_param == NULL); + if (priv->access_control_param != NULL) + tp_g_value_slice_free (priv->access_control_param); priv->access_control_param = tp_g_value_slice_dup (access_control_param); - if (priv->state != GABBLE_TUBE_CHANNEL_STATE_LOCAL_PENDING) - { - GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "Tube is not in the local pending state" }; - - dbus_g_method_return_error (context, &e); - return; - } - if (!gabble_tube_stream_accept (GABBLE_TUBE_IFACE (self), &error)) { dbus_g_method_return_error (context, error); diff --git a/src/tubes-channel.c b/src/tubes-channel.c index 7369733de..f4e93a44f 100644 --- a/src/tubes-channel.c +++ b/src/tubes-channel.c @@ -276,6 +276,7 @@ gabble_tubes_channel_get_property (GObject *object, TP_IFACE_CHANNEL, "InitiatorHandle", TP_IFACE_CHANNEL, "InitiatorID", TP_IFACE_CHANNEL, "Requested", + TP_IFACE_CHANNEL, "Interfaces", NULL)); break; default: @@ -1498,6 +1499,9 @@ tube_msg_offered (GabbleTubesChannel *self, tube = create_new_tube (self, type, priv->handle, service, parameters, NULL, tube_id, NULL); + + tp_channel_manager_emit_new_channel (priv->conn->private_tubes_factory, + TP_EXPORTABLE_CHANNEL (tube), NULL); } static void @@ -1917,26 +1921,6 @@ gabble_tubes_channel_accept_stream_tube (TpSvcChannelTypeTubes *iface, return; } - if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX) - { - error = g_error_new (TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, - "Address type %d not implemented", address_type); - - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - if (access_control != TP_SOCKET_ACCESS_CONTROL_LOCALHOST) - { - GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "Only the Localhost access control method is implemented by" - " Gabble" }; - - dbus_g_method_return_error (context, &e); - return; - } - g_object_get (tube, "type", &type, "state", &state, @@ -1951,15 +1935,18 @@ gabble_tubes_channel_accept_stream_tube (TpSvcChannelTypeTubes *iface, return; } - if (state != TP_TUBE_STATE_LOCAL_PENDING) + /* most parameters sanity checks are done in gabble_tube_stream_accept, + * but at least check that they fit the properties requirements */ + if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX && + address_type != TP_SOCKET_ADDRESS_TYPE_IPV4 && + address_type != TP_SOCKET_ADDRESS_TYPE_IPV6) { GError e = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, - "Tube is not in the local pending state" }; + "Address type not implemented" }; dbus_g_method_return_error (context, &e); return; } - g_object_set (tube, "address-type", address_type, "access-control", access_control, diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am index 94b40b3d4..3f4fa08ab 100644 --- a/tests/twisted/Makefile.am +++ b/tests/twisted/Makefile.am @@ -43,6 +43,7 @@ TWISTED_TESTS = \ tubes/test-muc-accept-stream-tube-ibb.py \ tubes/test-muc-offer-dbus-tube.py \ tubes/test-muc-offer-stream-tube-ibb.py \ + tubes/test-si-accept-tubes.py \ tubes/test-si-tubes.py \ tubes/ensure-si-tube.py \ vcard/test-alias-empty-vcard.py \ diff --git a/tests/twisted/roster/ensure.py b/tests/twisted/roster/ensure.py index fa1b507c8..44dfd61b6 100644 --- a/tests/twisted/roster/ensure.py +++ b/tests/twisted/roster/ensure.py @@ -43,14 +43,9 @@ def test(q, bus, conn, stream): ret = q.expect('dbus-return', method='EnsureChannel') ret2 = q.expect('dbus-return', method='EnsureChannel') - while True: - sig = q.expect('dbus-signal', signal='NewChannels') - sig_path, sig_props = sig.args[0][0] - if sig_props['org.freedesktop.Telepathy.Channel.TargetHandleType'] ==\ - HT_GROUP and\ - sig_props['org.freedesktop.Telepathy.Channel.TargetHandle'] ==\ - test_handle: - break + # We don't test the NewChannels signal here - depending on exact timing, + # it might happen between the two EnsureChannel calls, or after the second + # one. yours, path, props = ret.value yours2, path2, props2 = ret2.value @@ -68,8 +63,5 @@ def test(q, bus, conn, stream): assert path == path2, (path, path2) assert props == props2, (props, props2) - assert sig_props == props, (sig_props, props) - - if __name__ == '__main__': exec_test(test) diff --git a/tests/twisted/tools/tmp-session-bus.conf.in b/tests/twisted/tools/tmp-session-bus.conf.in index fd670fd89..84d8d656b 100644 --- a/tests/twisted/tools/tmp-session-bus.conf.in +++ b/tests/twisted/tools/tmp-session-bus.conf.in @@ -14,7 +14,7 @@ <policy context="default"> <!-- Allow everything to be sent --> - <allow send_destination="*"/> + <allow send_destination="*" eavesdrop="true"/> <!-- Allow everything to be received --> <allow eavesdrop="true"/> <!-- Allow anyone to own anything --> diff --git a/tests/twisted/tubes/test-si-accept-tubes.py b/tests/twisted/tubes/test-si-accept-tubes.py new file mode 100644 index 000000000..8e61d4ac7 --- /dev/null +++ b/tests/twisted/tubes/test-si-accept-tubes.py @@ -0,0 +1,269 @@ +""" +Receives several tube offers: +- Test to accept a 1-1 stream tube + - using UNIX sockets and IPv4 sockets + - using the old tube iface and the new tube iface +- Test to accept with bad parameters +- Test to refuse the tube offer + - using the old tube iface and the new tube iface +""" + +import dbus + +from servicetest import call_async, EventPattern, tp_name_prefix, \ + EventProtocolClientFactory +from gabbletest import exec_test, acknowledge_iq + +from twisted.words.xish import domish, xpath +from twisted.internet import reactor + +NS_TUBES = 'http://telepathy.freedesktop.org/xmpp/tubes' +NS_SI = 'http://jabber.org/protocol/si' +NS_IBB = 'http://jabber.org/protocol/ibb' + +bob_jid = 'bob@localhost/Bob' +stream_tube_id = 49 + +def receive_tube_offer(q, bus, conn, stream): + message = domish.Element(('jabber:client', 'message')) + message['to'] = 'test@localhost/Resource' + message['from'] = bob_jid + tube_node = message.addElement((NS_TUBES, 'tube')) + tube_node['type'] = 'stream' + tube_node['service'] = 'http' + tube_node['id'] = str(stream_tube_id) + stream.send(message) + + old_sig, new_sig = q.expect_many( + EventPattern('dbus-signal', signal='NewChannel'), + EventPattern('dbus-signal', signal='NewChannels'), + ) + chan_path = old_sig.args[0] + assert old_sig.args[1] == \ + 'org.freedesktop.Telepathy.Channel.Type.Tubes', \ + old_sig.args[1] + assert old_sig.args[2] == 1 # Handle_Type_Contact + bob_handle = old_sig.args[3] + assert old_sig.args[2] == 1, old_sig.args[2] # Suppress_Handler + assert len(new_sig.args) == 1 + assert len(new_sig.args[0]) == 1 + assert new_sig.args[0][0][0] == chan_path, new_sig.args[0][0] + assert new_sig.args[0][0][1] is not None + + event = q.expect('dbus-signal', signal='NewTube') + + old_sig, new_sig = q.expect_many( + EventPattern('dbus-signal', signal='NewChannel'), + EventPattern('dbus-signal', signal='NewChannels'), + ) + new_chan_path = old_sig.args[0] + assert new_chan_path != chan_path + assert old_sig.args[1] == \ + 'org.freedesktop.Telepathy.Channel.Type.StreamTube.DRAFT', \ + old_sig.args[1] + assert old_sig.args[2] == 1 # Handle_Type_Contact + bob_handle = old_sig.args[3] + assert old_sig.args[2] == 1, old_sig.args[2] # Suppress_Handler + assert len(new_sig.args) == 1 + assert len(new_sig.args[0]) == 1 + assert new_sig.args[0][0][0] == new_chan_path, new_sig.args[0][0] + assert new_sig.args[0][0][1] is not None + + # create channel proxies + tubes_chan = bus.get_object(conn.bus_name, chan_path) + tubes_iface = dbus.Interface(tubes_chan, + tp_name_prefix + '.Channel.Type.Tubes') + + new_tubes_chan = bus.get_object(conn.bus_name, new_chan_path) + new_tubes_iface = dbus.Interface(new_tubes_chan, + tp_name_prefix + '.Channel.Type.StreamTube.DRAFT') + + return (tubes_chan, tubes_iface, new_tubes_chan, new_tubes_iface) + +def expect_tube_activity(q, bus, conn, stream): + event_socket, event_iq = q.expect_many( + EventPattern('socket-connected'), + EventPattern('stream-iq', to=bob_jid, query_ns=NS_SI, + query_name='si')) + protocol = event_socket.protocol + protocol.sendData("hello initiator") + + iq = event_iq.stanza + si = xpath.queryForNodes('/iq/si[@xmlns="%s"]' % NS_SI, + iq)[0] + values = xpath.queryForNodes( + '/si/feature[@xmlns="%s"]/x[@xmlns="%s"]/field/option/value' + % ('http://jabber.org/protocol/feature-neg', 'jabber:x:data'), si) + assert NS_IBB in [str(v) for v in values] + + stream_node = xpath.queryForNodes('/si/stream[@xmlns="%s"]' % + NS_TUBES, si)[0] + assert stream_node is not None + assert stream_node['tube'] == str(stream_tube_id) + stream_id = si['id'] + +def test(q, bus, conn, stream): + conn.Connect() + + _, vcard_event, roster_event = q.expect_many( + EventPattern('dbus-signal', signal='StatusChanged', args=[0, 1]), + EventPattern('stream-iq', to=None, query_ns='vcard-temp', + query_name='vCard'), + EventPattern('stream-iq', query_ns='jabber:iq:roster')) + + acknowledge_iq(stream, vcard_event.stanza) + + roster = roster_event.stanza + roster['type'] = 'result' + item = roster_event.query.addElement('item') + item['jid'] = 'bob@localhost' # Bob can do tubes + item['subscription'] = 'both' + stream.send(roster) + + # Send Bob presence and his caps + presence = domish.Element(('jabber:client', 'presence')) + presence['from'] = 'bob@localhost/Bob' + presence['to'] = 'test@localhost/Resource' + c = presence.addElement('c') + c['xmlns'] = 'http://jabber.org/protocol/caps' + c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy' + c['ver'] = '1.2.3' + stream.send(presence) + + event = q.expect('stream-iq', iq_type='get', + query_ns='http://jabber.org/protocol/disco#info', + to='bob@localhost/Bob') + result = event.stanza + result['type'] = 'result' + assert event.query['node'] == \ + 'http://example.com/ICantBelieveItsNotTelepathy#1.2.3' + feature = event.query.addElement('feature') + feature['var'] = NS_TUBES + stream.send(result) + + # Receive a tube offer from Bob + (tubes_chan, tubes_iface, new_tubes_chan, new_tubes_iface) = \ + receive_tube_offer(q, bus, conn, stream) + + # Try bad parameters on the old iface + call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id+1, 2, 0, '', + byte_arrays=True) + q.expect('dbus-error', method='AcceptStreamTube') + call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, 2, 1, '', + byte_arrays=True) + q.expect('dbus-error', method='AcceptStreamTube') + call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, 20, 0, '', + byte_arrays=True) + q.expect('dbus-error', method='AcceptStreamTube') + + # Try bad parameters on the new iface + call_async(q, new_tubes_iface, 'AcceptStreamTube', 20, 0, '', + byte_arrays=True) + q.expect('dbus-error', method='AcceptStreamTube') + call_async(q, new_tubes_iface, 'AcceptStreamTube', 0, 1, '', + byte_arrays=True) + q.expect('dbus-error', method='AcceptStreamTube') + + # Accept the tube with old iface, and use IPv4 + call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, 2, 0, '', + byte_arrays=True) + + accept_return_event, _ = q.expect_many( + EventPattern('dbus-return', method='AcceptStreamTube'), + EventPattern('dbus-signal', signal='TubeStateChanged', + args=[stream_tube_id, 2])) + + ip = accept_return_event.value[0][0] + port = accept_return_event.value[0][1] + assert port > 0 + + factory = EventProtocolClientFactory(q) + reactor.connectTCP(ip, port, factory) + + expect_tube_activity(q, bus, conn, stream) + tubes_chan.Close() + + # Receive a tube offer from Bob + (tubes_chan, tubes_iface, new_tubes_chan, new_tubes_iface) = \ + receive_tube_offer(q, bus, conn, stream) + + # Accept the tube with old iface, and use UNIX sockets + call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, 0, 0, '', + byte_arrays=True) + + accept_return_event, _ = q.expect_many( + EventPattern('dbus-return', method='AcceptStreamTube'), + EventPattern('dbus-signal', signal='TubeStateChanged', + args=[stream_tube_id, 2])) + + socket_address = accept_return_event.value[0] + + factory = EventProtocolClientFactory(q) + reactor.connectUNIX(socket_address, factory) + + expect_tube_activity(q, bus, conn, stream) + tubes_chan.Close() + + # Receive a tube offer from Bob + (tubes_chan, tubes_iface, new_tubes_chan, new_tubes_iface) = \ + receive_tube_offer(q, bus, conn, stream) + + # Accept the tube with new iface, and use IPv4 + call_async(q, new_tubes_iface, 'AcceptStreamTube', 2, 0, '', + byte_arrays=True) + + accept_return_event, _ = q.expect_many( + EventPattern('dbus-return', method='AcceptStreamTube'), + EventPattern('dbus-signal', signal='TubeStateChanged', + args=[stream_tube_id, 2])) + + ip = accept_return_event.value[0][0] + port = accept_return_event.value[0][1] + assert port > 0 + + factory = EventProtocolClientFactory(q) + reactor.connectTCP(ip, port, factory) + + expect_tube_activity(q, bus, conn, stream) + tubes_chan.Close() + + # Receive a tube offer from Bob + (tubes_chan, tubes_iface, new_tubes_chan, new_tubes_iface) = \ + receive_tube_offer(q, bus, conn, stream) + + # Accept the tube with new iface, and use UNIX sockets + call_async(q, new_tubes_iface, 'AcceptStreamTube', 0, 0, '', + byte_arrays=True) + + accept_return_event, _ = q.expect_many( + EventPattern('dbus-return', method='AcceptStreamTube'), + EventPattern('dbus-signal', signal='TubeStateChanged', + args=[stream_tube_id, 2])) + + socket_address = accept_return_event.value[0] + + factory = EventProtocolClientFactory(q) + reactor.connectUNIX(socket_address, factory) + + expect_tube_activity(q, bus, conn, stream) + tubes_chan.Close() + + # Receive a tube offer from Bob + (tubes_chan, tubes_iface, new_tubes_chan, new_tubes_iface) = \ + receive_tube_offer(q, bus, conn, stream) + # Just close the tube + tubes_chan.Close() + + # Receive a tube offer from Bob + (tubes_chan, tubes_iface, new_tubes_chan, new_tubes_iface) = \ + receive_tube_offer(q, bus, conn, stream) + # Just close the tube + new_tubes_chan.Close() + + # OK, we're done + conn.Disconnect() + + q.expect('dbus-signal', signal='StatusChanged', args=[2, 1]) + +if __name__ == '__main__': + exec_test(test) diff --git a/tests/twisted/tubes/test-si-tubes.py b/tests/twisted/tubes/test-si-tubes.py index 4a07f7de6..ace124b25 100644 --- a/tests/twisted/tubes/test-si-tubes.py +++ b/tests/twisted/tubes/test-si-tubes.py @@ -8,8 +8,9 @@ import dbus from dbus.connection import Connection from dbus.lowlevel import SignalMessage -from servicetest import call_async, EventPattern, tp_name_prefix, watch_tube_signals -from gabbletest import exec_test, acknowledge_iq +from servicetest import call_async, EventPattern, tp_name_prefix, \ + watch_tube_signals, sync_dbus +from gabbletest import exec_test, acknowledge_iq, sync_stream from twisted.words.xish import domish, xpath from twisted.internet.protocol import Factory, Protocol @@ -184,10 +185,33 @@ def test(q, bus, conn, stream): roster = roster_event.stanza roster['type'] = 'result' item = roster_event.query.addElement('item') - item['jid'] = 'bob@localhost' + item['jid'] = 'bob@localhost' # Bob can do tubes + item['subscription'] = 'both' + item = roster_event.query.addElement('item') + item['jid'] = 'joe@localhost' # Joe cannot do tubes item['subscription'] = 'both' stream.send(roster) + # Send Joe presence is without tube caps + presence = domish.Element(('jabber:client', 'presence')) + presence['from'] = 'joe@localhost/Joe' + presence['to'] = 'test@localhost/Resource' + c = presence.addElement('c') + c['xmlns'] = 'http://jabber.org/protocol/caps' + c['node'] = 'http://example.com/IDontSupportTubes' + c['ver'] = '1.0' + stream.send(presence) + + event = q.expect('stream-iq', iq_type='get', + query_ns='http://jabber.org/protocol/disco#info', + to='joe@localhost/Joe') + result = event.stanza + result['type'] = 'result' + assert event.query['node'] == \ + 'http://example.com/IDontSupportTubes#1.0' + stream.send(result) + + # Send Bob presence and his tube caps presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'bob@localhost/Bob' presence['to'] = 'test@localhost/Resource' @@ -208,6 +232,38 @@ def test(q, bus, conn, stream): feature['var'] = NS_TUBES stream.send(result) + # A tube request can be done only if the contact has tube capabilities + # Ensure that Joe and Bob's caps have been received + sync_stream(q, stream) + + # new requestotron + requestotron = dbus.Interface(conn, + 'org.freedesktop.Telepathy.Connection.Interface.Requests') + + # Test tubes with Joe. Joe does not have tube capabilities. + # Gabble does not allow to offer a tube to him. + joe_handle = conn.RequestHandles(1, ['joe@localhost'])[0] + call_async(q, conn, 'RequestChannel', + tp_name_prefix + '.Channel.Type.Tubes', 1, joe_handle, True); + + ret, old_sig, new_sig = q.expect_many( + EventPattern('dbus-return', method='RequestChannel'), + EventPattern('dbus-signal', signal='NewChannel'), + EventPattern('dbus-signal', signal='NewChannels'), + ) + joe_chan_path = ret.value[0] + + joe_tubes_chan = bus.get_object(conn.bus_name, joe_chan_path) + joe_tubes_iface = dbus.Interface(joe_tubes_chan, + tp_name_prefix + '.Channel.Type.Tubes') + path = os.getcwd() + '/stream' + call_async(q, joe_tubes_iface, 'OfferStreamTube', + 'echo', sample_parameters, 0, dbus.ByteArray(path), 0, "") + event = q.expect('dbus-error', method='OfferStreamTube') + + joe_tubes_chan.Close() + + # Test tubes with Bob. Bob does not have tube capabilities. bob_handle = conn.RequestHandles(1, ['bob@localhost'])[0] # old requestotron @@ -230,10 +286,6 @@ def test(q, bus, conn, stream): check_conn_properties(q, bus, conn, stream, [old_tubes_channel_properties]) - # new requestotron - requestotron = dbus.Interface(conn, - 'org.freedesktop.Telepathy.Connection.Interface.Requests') - # Try to CreateChannel with unknown properties # Gabble must return an error call_async(q, requestotron, 'CreateChannel', @@ -310,12 +362,12 @@ def test(q, bus, conn, stream): bob_handle, "bob@localhost") # Offer the tube, old API - path = os.getcwd() + '/stream' call_async(q, tubes_iface, 'OfferStreamTube', 'echo', sample_parameters, 0, dbus.ByteArray(path), 0, "") event = q.expect('stream-message') message = event.stanza + assert message['to'] == 'bob@localhost/Bob' # check the resource tube_nodes = xpath.queryForNodes('/message/tube[@xmlns="%s"]' % NS_TUBES, message) assert tube_nodes is not None @@ -398,6 +450,7 @@ def test(q, bus, conn, stream): event = q.expect('stream-message') message = event.stanza + assert message['to'] == 'bob@localhost/Bob' # check the resource tube_nodes = xpath.queryForNodes('/message/tube[@xmlns="%s"]' % NS_TUBES, message) assert tube_nodes is not None diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py index 36f3242b0..9eb7af5ce 100644 --- a/tools/glib-ginterface-gen.py +++ b/tools/glib-ginterface-gen.py @@ -588,10 +588,21 @@ class Generator(object): self.b('}') self.b('') + signal_name = dbus_gutils_wincaps_to_uscore(dbus_name).replace('_', + '-') + in_base_init.append(' /**') + in_base_init.append(' * %s%s::%s:' + % (self.Prefix, self.node_name_mixed, signal_name)) + for (ctype, name, gtype) in args: + in_base_init.append(' * @%s: %s (FIXME, generate documentation)' + % (name, ctype)) + in_base_init.append(' *') + in_base_init.append(' * The %s D-Bus signal is emitted whenever ' + 'this GObject signal is.' % dbus_name) + in_base_init.append(' */') in_base_init.append(' %s_signals[%s] =' % (self.node_name_lc, const_name)) - in_base_init.append(' g_signal_new ("%s",' - % (dbus_gutils_wincaps_to_uscore(dbus_name).replace('_', '-'))) + in_base_init.append(' g_signal_new ("%s",' % signal_name) in_base_init.append(' G_OBJECT_CLASS_TYPE (klass),') in_base_init.append(' G_SIGNAL_RUN_LAST|G_SIGNAL_DETAILED,') in_base_init.append(' 0,') diff --git a/tools/telepathy.am b/tools/telepathy.am index f0fe870a2..d061b8918 100644 --- a/tools/telepathy.am +++ b/tools/telepathy.am @@ -7,7 +7,9 @@ dist-hook: git log > ${distdir}/ChangeLog; \ fi -maintainer-upload-release: +maintainer-upload-release: _maintainer-upload-release + +_maintainer-upload-release-check: @case @VERSION@ in \ (*.*.*.*) \ echo "@VERSION@ is not a release" >&2; \ @@ -17,6 +19,9 @@ maintainer-upload-release: test -f @PACKAGE@-@VERSION@.tar.gz test -f @PACKAGE@-@VERSION@.tar.gz.asc gpg --verify @PACKAGE@-@VERSION@.tar.gz.asc + +_maintainer-upload-release: _maintainer-upload-release-check rsync -vzP @PACKAGE@-@VERSION@.tar.gz telepathy.freedesktop.org:/srv/telepathy.freedesktop.org/www/releases/@PACKAGE@/@PACKAGE@-@VERSION@.tar.gz + rsync -vzP @PACKAGE@-@VERSION@.tar.gz.asc telepathy.freedesktop.org:/srv/telepathy.freedesktop.org/www/releases/@PACKAGE@/@PACKAGE@-@VERSION@.tar.gz.asc ## vim:set ft=automake: |