[Telepathy-commits] [telepathy-gabble/master] Channel.Type.{Stream|DBus}Tube are requestable with the new requestotron.
Alban Crequy
alban.crequy at collabora.co.uk
Mon Nov 3 11:20:57 PST 2008
- GabblePrivateTubesFactory is a Channel Factory for both
Channel.Type.Tubes and the new Channel.Type.{Stream|DBus}Tube
objects.
- GabbleTubeStream implements the Channel.FUTURE properties
- GabbleTubesChannel object has an helper function
gabble_tubes_channel_tube_request for the factory. The function
creates the tube channel with the new API.
- The unit test test-si-tubes.py request a stream tube channel
with the new API.
---
src/private-tubes-factory.c | 83 +++++++++++++++++++-----
src/tube-stream.c | 72 +++++++++++++++++++++
src/tubes-channel.c | 45 +++++++++++++
src/tubes-channel.h | 5 ++
tests/twisted/tubes/test-si-tubes.py | 115 +++++++++++++++++++++++++++++----
5 files changed, 289 insertions(+), 31 deletions(-)
diff --git a/src/private-tubes-factory.c b/src/private-tubes-factory.c
index 6004e9d..1a75a19 100644
--- a/src/private-tubes-factory.c
+++ b/src/private-tubes-factory.c
@@ -640,10 +640,15 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
base_conn, TP_HANDLE_TYPE_CONTACT);
TpHandle handle;
GError *error = NULL;
- GabbleExportableChannel *channel;
+ const gchar *channel_type;
+ GabbleTubesChannel *channel;
- if (tp_strdiff (tp_asv_get_string (request_properties,
- TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_TUBES))
+ channel_type = tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType");
+
+ if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES) &&
+ tp_strdiff (channel_type, GABBLE_IFACE_CHANNEL_TYPE_STREAM_TUBE) &&
+ tp_strdiff (channel_type, GABBLE_IFACE_CHANNEL_TYPE_DBUS_TUBE))
return FALSE;
if (tp_asv_get_uint32 (request_properties,
@@ -659,30 +664,74 @@ gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
/* Don't support opening a channel to our self handle */
if (handle == base_conn->self_handle)
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Can't open a channel to your self handle");
- goto error;
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "Can't open a channel to your self handle");
+ goto error;
}
channel = g_hash_table_lookup (self->priv->channels,
GUINT_TO_POINTER (handle));
- if (channel == NULL)
+ if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES))
{
- new_tubes_channel (self, handle, base_conn->self_handle, request_token);
+ if (channel == NULL)
+ {
+ channel = new_tubes_channel (self, handle, base_conn->self_handle,
+ request_token);
+ return TRUE;
+ }
+
+ 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",
+ handle);
+ goto error;
+ }
+
+ gabble_channel_manager_emit_request_already_satisfied (self,
+ request_token, GABBLE_EXPORTABLE_CHANNEL (channel));
return TRUE;
}
-
- if (require_new)
+ else
{
- g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "Already chatting with contact #%u in another channel", handle);
- goto error;
- }
+ GabbleTubeIface *new_channel;
- gabble_channel_manager_emit_request_already_satisfied (self, request_token,
- channel);
- return TRUE;
+ if (channel == NULL)
+ {
+ channel = new_tubes_channel (self, handle, base_conn->self_handle,
+ request_token);
+ }
+ g_assert (channel != NULL);
+
+ new_channel = gabble_tubes_channel_tube_request (channel, request_token,
+ request_properties, require_new);
+ if (new_channel != NULL)
+ {
+ GSList *request_tokens;
+
+ tp_channel_factory_iface_emit_new_channel (self,
+ TP_CHANNEL_IFACE (new_channel), request_token);
+
+ if (request_token != NULL)
+ request_tokens = g_slist_prepend (NULL, request_token);
+ else
+ request_tokens = NULL;
+
+ gabble_channel_manager_emit_new_channel (self,
+ GABBLE_EXPORTABLE_CHANNEL (new_channel), request_tokens);
+
+ g_slist_free (request_tokens);
+ }
+ else
+ {
+ gabble_channel_manager_emit_request_already_satisfied (self,
+ request_token, GABBLE_EXPORTABLE_CHANNEL (channel));
+ }
+
+ return TRUE;
+ }
error:
gabble_channel_manager_emit_request_failed (self, request_token,
diff --git a/src/tube-stream.c b/src/tube-stream.c
index e24f9d9..ea23a87 100644
--- a/src/tube-stream.c
+++ b/src/tube-stream.c
@@ -128,6 +128,10 @@ enum
PROP_ACCESS_CONTROL_PARAM,
PROP_CHANNEL_DESTROYED,
PROP_CHANNEL_PROPERTIES,
+ PROP_REQUESTED,
+ PROP_TARGET_ID,
+ PROP_INITIATOR_HANDLE,
+ PROP_INITIATOR_ID,
LAST_PROPERTY
};
@@ -975,6 +979,7 @@ gabble_tube_stream_get_property (GObject *object,
{
GabbleTubeStream *self = GABBLE_TUBE_STREAM (object);
GabbleTubeStreamPrivate *priv = GABBLE_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
switch (property_id)
{
@@ -1042,6 +1047,36 @@ gabble_tube_stream_get_property (GObject *object,
GABBLE_IFACE_CHANNEL_FUTURE, "Requested",
NULL));
break;
+ case PROP_REQUESTED:
+ g_value_set_boolean (value,
+ (priv->initiator == priv->self_handle));
+ break;
+ case PROP_INITIATOR_ID:
+ if (priv->initiator == 0)
+ {
+ g_value_set_static_string (value, "");
+ }
+ else
+ {
+ TpHandleRepoIface *repo = tp_base_connection_get_handles (
+ base_conn, TP_HANDLE_TYPE_CONTACT);
+
+ g_value_set_string (value,
+ tp_handle_inspect (repo, priv->initiator));
+ }
+ break;
+ case PROP_TARGET_ID:
+ {
+ TpHandleRepoIface *repo = tp_base_connection_get_handles (
+ base_conn, priv->handle_type);
+
+ g_value_set_string (value,
+ tp_handle_inspect (repo, priv->handle));
+ }
+ break;
+ case PROP_INITIATOR_HANDLE:
+ g_value_set_uint (value, priv->initiator);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -1118,6 +1153,13 @@ gabble_tube_stream_set_property (GObject *object,
g_value_get_pointer (value));
}
break;
+ case PROP_INITIATOR_HANDLE:
+ /* PROP_INITIATOR_HANDLE and PROP_INITIATOR are the same property from
+ * two different interfaces (Channel.FUTURE and
+ * Channel.Interface.Tube.DRAFT). In case of tube channels, this can
+ * never be 0. The value is stored in priv->initiator. The object is
+ * created only with PROP_INITIATOR set, so do nothing here. */
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -1319,6 +1361,36 @@ gabble_tube_stream_class_init (GabbleTubeStreamClass *gabble_tube_stream_class)
g_object_class_install_property (object_class, PROP_ACCESS_CONTROL_PARAM,
param_spec);
+ 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_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_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_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_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
+
signals[OPENED] =
g_signal_new ("tube-opened",
G_OBJECT_CLASS_TYPE (gabble_tube_stream_class),
diff --git a/src/tubes-channel.c b/src/tubes-channel.c
index 901f7e4..c1bc420 100644
--- a/src/tubes-channel.c
+++ b/src/tubes-channel.c
@@ -1582,6 +1582,51 @@ generate_tube_id (void)
return g_random_int_range (0, G_MAXINT);
}
+GabbleTubeIface *gabble_tubes_channel_tube_request (GabbleTubesChannel *self,
+ gpointer request_token, GHashTable *request_properties,
+ gboolean require_new)
+{
+ GabbleTubesChannelPrivate *priv = GABBLE_TUBES_CHANNEL_GET_PRIVATE (self);
+ GabbleTubeIface *tube;
+ const gchar *channel_type;
+ const gchar *service;
+ GHashTable *parameters = NULL;
+ guint tube_id;
+ TpTubeType type;
+
+ tube_id = generate_tube_id ();
+
+ parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) tp_g_value_slice_free);
+
+ channel_type = tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType");
+
+ if (! tp_strdiff (channel_type, GABBLE_IFACE_CHANNEL_TYPE_STREAM_TUBE))
+ {
+ type = TP_TUBE_TYPE_STREAM;
+ service = tp_asv_get_string (request_properties,
+ GABBLE_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service");
+
+ }
+ else if (! tp_strdiff (channel_type, GABBLE_IFACE_CHANNEL_TYPE_DBUS_TUBE))
+ {
+ type = TP_TUBE_TYPE_DBUS;
+ service = tp_asv_get_string (request_properties,
+ GABBLE_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName");
+ }
+ else
+ g_assert_not_reached ();
+
+ DEBUG ("Request a tube channel with type='%s' and service='%s'",
+ channel_type, service);
+
+ tube = create_new_tube (self, type, priv->self_handle, service,
+ parameters, NULL, tube_id, NULL);
+
+ return tube;
+}
+
/**
* gabble_tubes_channel_offer_d_bus_tube
*
diff --git a/src/tubes-channel.h b/src/tubes-channel.h
index 2f71b19..92f25a9 100644
--- a/src/tubes-channel.h
+++ b/src/tubes-channel.h
@@ -28,6 +28,7 @@
#include "bytestream-iface.h"
#include "exportable-channel.h"
#include "muc-channel.h"
+#include "tube-iface.h"
G_BEGIN_DECLS
@@ -71,6 +72,10 @@ GType gabble_tubes_channel_get_type (void);
void gabble_tubes_channel_foreach (GabbleTubesChannel *self,
GabbleExportableChannelFunc foreach, gpointer user_data);
+GabbleTubeIface *gabble_tubes_channel_tube_request (GabbleTubesChannel *self,
+ gpointer request_token, GHashTable *request_properties,
+ gboolean require_new);
+
void gabble_tubes_channel_presence_updated (GabbleTubesChannel *chan,
TpHandle contact, LmMessage *presence);
diff --git a/tests/twisted/tubes/test-si-tubes.py b/tests/twisted/tubes/test-si-tubes.py
index 23371a6..4f569c7 100644
--- a/tests/twisted/tubes/test-si-tubes.py
+++ b/tests/twisted/tubes/test-si-tubes.py
@@ -63,6 +63,14 @@ def test(q, bus, conn, stream):
[]
) in properties.get('RequestableChannelClasses'),\
properties['RequestableChannelClasses']
+ assert ({'org.freedesktop.Telepathy.Channel.ChannelType':
+ 'org.freedesktop.Telepathy.Channel.Type.StreamTube.DRAFT',
+ 'org.freedesktop.Telepathy.Channel.TargetHandleType': 1,
+ },
+ ['org.freedesktop.Telepathy.Channel.TargetHandle'],
+ []
+ ) in properties.get('RequestableChannelClasses'),\
+ properties['RequestableChannelClasses']
_, vcard_event, roster_event = q.expect_many(
EventPattern('dbus-signal', signal='StatusChanged', args=[0, 1]),
@@ -101,6 +109,7 @@ def test(q, bus, conn, stream):
bob_handle = conn.RequestHandles(1, ['bob at localhost'])[0]
+ # old requestotron
call_async(q, conn, 'RequestChannel',
tp_name_prefix + '.Channel.Type.Tubes', 1, bob_handle, True);
@@ -110,7 +119,6 @@ def test(q, bus, conn, stream):
EventPattern('dbus-signal', signal='NewChannels'),
)
-
assert len(ret.value) == 1
chan_path = ret.value[0]
@@ -146,6 +154,85 @@ def test(q, bus, conn, stream):
assert new_sig.args[0][0] in properties['Channels'], \
(new_sig.args[0][0], properties['Channels'])
+ # new requestotron
+ requestotron = dbus.Interface(conn,
+ 'org.freedesktop.Telepathy.Connection.Interface.Requests.DRAFT')
+
+# call_async(q, requestotron, 'CreateChannel',
+# {'org.freedesktop.Telepathy.Channel.ChannelType':
+# 'org.freedesktop.Telepathy.Channel.Type.StreamTube.DRAFT',
+# 'org.freedesktop.Telepathy.Channel.TargetHandleType':
+# 1,
+# 'org.freedesktop.Telepathy.Channel.TargetHandle':
+# bob_handle
+# });
+# # some properties are missing in the request, we expect gabble to return
+# # the relevent error
+# ret = q.expect_many(EventPattern('dbus-error', method='CreateChannel'))
+
+ call_async(q, requestotron, 'CreateChannel',
+ {'org.freedesktop.Telepathy.Channel.ChannelType':
+ 'org.freedesktop.Telepathy.Channel.Type.StreamTube.DRAFT',
+ 'org.freedesktop.Telepathy.Channel.TargetHandleType':
+ 1,
+ 'org.freedesktop.Telepathy.Channel.TargetHandle':
+ bob_handle,
+ 'org.freedesktop.Telepathy.Channel.Type.StreamTube.DRAFT.Service':
+ "newecho",
+ });
+
+ ret, old_sig, new_sig = q.expect_many(
+ EventPattern('dbus-return', method='CreateChannel'),
+ EventPattern('dbus-signal', signal='NewChannel'),
+ EventPattern('dbus-signal', signal='NewChannels'),
+ )
+
+ assert len(ret.value) == 2 # CreateChannel returns 2 values: o, a{sv}
+ new_chan_path = ret.value[0]
+ new_chan_prop_asv = ret.value[1]
+ assert new_chan_path.find("StreamTube") != -1, new_chan_path
+ assert new_chan_path.find("SITubesChannel") == -1, new_chan_path
+ # The path of the Channel.Type.Tubes object MUST be different to the path
+ # of the Channel.Type.StreamTube object !
+ assert chan_path != new_chan_path
+
+ print "new_chan_path = " + new_chan_path
+ print "chan_path = " + chan_path
+
+ assert old_sig.args[0] == new_chan_path
+ assert old_sig.args[1] == tp_name_prefix + '.Channel.Type.StreamTube.DRAFT', old_sig.args[1]
+ assert old_sig.args[2] == 1 # contact handle
+ assert old_sig.args[3] == bob_handle
+ assert old_sig.args[4] == True # suppress handler
+
+ assert len(new_sig.args) == 1
+ assert len(new_sig.args[0]) == 1 # one channel
+ assert len(new_sig.args[0][0]) == 2 # two struct members
+ assert new_sig.args[0][0][0] == ret.value[0]
+ emitted_props = new_sig.args[0][0][1]
+ print str(emitted_props)
+
+ assert emitted_props[tp_name_prefix + '.Channel.ChannelType'] ==\
+ tp_name_prefix + '.Channel.Type.StreamTube.DRAFT'
+ assert emitted_props[tp_name_prefix + '.Channel.TargetHandleType'] == 1
+ assert emitted_props[tp_name_prefix + '.Channel.TargetHandle'] ==\
+ bob_handle
+ assert emitted_props[tp_name_prefix + '.Channel.FUTURE.Requested'] == True
+ assert emitted_props[tp_name_prefix + '.Channel.FUTURE.TargetID'] == \
+ 'bob at localhost', emitted_props[tp_name_prefix + '.Channel.FUTURE.TargetID']
+ assert emitted_props[tp_name_prefix + '.Channel.FUTURE.InitiatorHandle'] \
+ == conn.GetSelfHandle()
+ assert emitted_props[tp_name_prefix + '.Channel.FUTURE.InitiatorID'] == \
+ 'test at localhost'
+
+ properties = conn.GetAll(
+ 'org.freedesktop.Telepathy.Connection.Interface.Requests.DRAFT',
+ dbus_interface='org.freedesktop.DBus.Properties')
+
+ assert new_sig.args[0][0] in properties['Channels'], \
+ (new_sig.args[0][0], properties['Channels'])
+
+ ## following
tubes_chan = bus.get_object(conn.bus_name, chan_path)
tubes_iface = dbus.Interface(tubes_chan,
tp_name_prefix + '.Channel.Type.Tubes')
@@ -208,18 +295,15 @@ def test(q, bus, conn, stream):
'u': ('uint', '123'),
}
- # We offered a tube using the old tube API. Check the new tube API works
+ # We offered a tube using the old tube API and with the new API, so there
+ # is 2 tubes. Check the new tube API works
assert len(filter(lambda x:
x[1] == "org.freedesktop.Telepathy.Channel.Type.Tubes",
conn.ListChannels())) == 1
- assert len(filter(lambda x:
- x[1] == "org.freedesktop.Telepathy.Channel.Type.StreamTube.DRAFT",
- conn.ListChannels())) == 1
-
channels = filter(lambda x: x[1]
== "org.freedesktop.Telepathy.Channel.Type.StreamTube.DRAFT",
conn.ListChannels())
- assert len(channels) == 1
+ assert len(channels) == 2
tube_chan = bus.get_object(conn.bus_name, channels[0][0])
tube_iface = dbus.Interface(tubes_chan,
@@ -228,7 +312,7 @@ def test(q, bus, conn, stream):
stream_tube_props = tube_chan.GetAll(
'org.freedesktop.Telepathy.Channel.Type.StreamTube.DRAFT',
dbus_interface='org.freedesktop.DBus.Properties')
- assert stream_tube_props.get("Service") == "echo"
+ assert stream_tube_props.get("Service") == "newecho", stream_tube_props
tube_props = tube_chan.GetAll(
'org.freedesktop.Telepathy.Channel.Interface.Tube.DRAFT',
@@ -240,7 +324,9 @@ def test(q, bus, conn, stream):
# 'i': ('int', '-123'),
# 'u': ('uint', '123'),
# }
- assert tube_props.get("Status") == 1 # Tube_Channel_State_Remote_Pending
+
+ # 3 == Tube_Channel_State_Not_Offered
+ assert tube_props.get("Status") == 3, tube_props
# The CM is the server, so fake a client wanting to talk to it
iq = IQ(stream, 'set')
@@ -281,14 +367,14 @@ def test(q, bus, conn, stream):
args=[stream_tube_id, bob_handle])
tubes = tubes_iface.ListTubes(byte_arrays=True)
- assert tubes == [(
+ assert (
stream_tube_id,
self_handle,
1, # Unix stream
'echo',
sample_parameters,
2, # OPEN
- )]
+ ) in tubes
# have the fake client open the stream
iq = IQ(stream, 'set')
@@ -400,21 +486,22 @@ def test(q, bus, conn, stream):
args=[dbus_tube_id, 2]) # 2 == OPEN
tubes = tubes_iface.ListTubes(byte_arrays=True)
- assert sorted(tubes) == sorted([(
+ assert (
dbus_tube_id,
self_handle,
0, # DBUS
'com.example.TestCase',
sample_parameters,
2, # OPEN
- ),(
+ ) in tubes
+ assert (
stream_tube_id,
self_handle,
1, # stream
'echo',
sample_parameters,
2, # OPEN
- )])
+ ) in tubes
dbus_tube_adr = tubes_iface.GetDBusTubeAddress(dbus_tube_id)
dbus_tube_conn = Connection(dbus_tube_adr)
--
1.5.6.5
More information about the Telepathy-commits
mailing list