summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS53
-rw-r--r--configure.ac2
-rw-r--r--src/im-channel.c1
-rw-r--r--src/im-factory.c12
-rw-r--r--src/media-channel.c1
-rw-r--r--src/media-factory.c30
-rw-r--r--src/media-stream.c47
-rw-r--r--src/muc-channel.c1
-rw-r--r--src/muc-factory.c7
-rw-r--r--src/olpc-activity-view.c6
-rw-r--r--src/olpc-activity.c24
-rw-r--r--src/olpc-buddy-view.c6
-rw-r--r--src/olpc-gadget-manager.c12
-rw-r--r--src/olpc-view.c30
-rw-r--r--src/private-tubes-factory.c11
-rw-r--r--src/roomlist-channel.c1
-rw-r--r--src/roomlist-manager.c6
-rw-r--r--src/roster-channel.c1
-rw-r--r--src/tube-dbus.c32
-rw-r--r--src/tube-iface.c51
-rw-r--r--src/tube-stream.c298
-rw-r--r--src/tubes-channel.c33
-rw-r--r--tests/twisted/Makefile.am1
-rw-r--r--tests/twisted/roster/ensure.py14
-rw-r--r--tests/twisted/tools/tmp-session-bus.conf.in2
-rw-r--r--tests/twisted/tubes/test-si-accept-tubes.py269
-rw-r--r--tests/twisted/tubes/test-si-tubes.py69
-rw-r--r--tools/glib-ginterface-gen.py15
-rw-r--r--tools/telepathy.am7
29 files changed, 678 insertions, 364 deletions
diff --git a/NEWS b/NEWS
index 1818a7e0d..4b9129ee7 100644
--- a/NEWS
+++ b/NEWS
@@ -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: