[Telepathy-commits] [telepathy-gabble/master] Implement EnsureChannel for media calls, and add a corresponding test

Will Thompson will.thompson at collabora.co.uk
Thu Sep 25 09:31:15 PDT 2008


---
 src/media-factory.c                               |   36 ++++
 tests/twisted/Makefile.am                         |    1 +
 tests/twisted/jingle/test-outgoing-call-ensure.py |  215 +++++++++++++++++++++
 3 files changed, 252 insertions(+), 0 deletions(-)
 create mode 100644 tests/twisted/jingle/test-outgoing-call-ensure.py

diff --git a/src/media-factory.c b/src/media-factory.c
index 96ab545..e167f4f 100644
--- a/src/media-factory.c
+++ b/src/media-factory.c
@@ -888,6 +888,7 @@ typedef enum
 {
   METHOD_REQUEST,
   METHOD_CREATE,
+  METHOD_ENSURE,
 } RequestMethod;
 
 
@@ -920,6 +921,10 @@ gabble_media_factory_requestotron (TpChannelManager *manager,
    *     channel has TargetHandle=n
    *     n is not in the group interface at all
    *     call is started when caller calls RequestStreams.
+   * - EnsureChannel({THT: Contact, TH: n}):
+   *     look for a channel whose peer is n, and return that if found with
+   *       whatever properties and group membership it has;
+   *     otherwise the same as into CreateChannel
    */
   switch (method)
     {
@@ -928,6 +933,7 @@ gabble_media_factory_requestotron (TpChannelManager *manager,
       add_peer_to_remote_pending = TRUE;
       break;
     case METHOD_CREATE:
+    case METHOD_ENSURE:
       require_target_handle = TRUE;
       add_peer_to_remote_pending = FALSE;
       break;
@@ -984,6 +990,25 @@ gabble_media_factory_requestotron (TpChannelManager *manager,
               &error))
         goto error;
 
+      if (method == METHOD_ENSURE)
+        {
+          guint i;
+          TpHandle peer = 0;
+
+          for (i = 0; i < priv->channels->len; i++)
+            {
+              channel = g_ptr_array_index (priv->channels, i);
+              g_object_get (channel, "peer", &peer, NULL);
+
+              if (peer == handle)
+                {
+                  tp_channel_manager_emit_request_already_satisfied (self,
+                      request_token, TP_EXPORTABLE_CHANNEL (channel));
+                  return TRUE;
+                }
+            }
+        }
+
       channel = new_media_channel (self, conn->self_handle, handle);
 
       if (add_peer_to_remote_pending)
@@ -1039,6 +1064,16 @@ gabble_media_factory_create_channel (TpChannelManager *manager,
 }
 
 
+static gboolean
+gabble_media_factory_ensure_channel (TpChannelManager *manager,
+                                     gpointer request_token,
+                                     GHashTable *request_properties)
+{
+  return gabble_media_factory_requestotron (manager, request_token,
+      request_properties, METHOD_ENSURE);
+}
+
+
 static void
 channel_manager_iface_init (gpointer g_iface,
                             gpointer iface_data)
@@ -1049,4 +1084,5 @@ channel_manager_iface_init (gpointer g_iface,
   iface->foreach_channel_class = gabble_media_factory_foreach_channel_class;
   iface->request_channel = gabble_media_factory_request_channel;
   iface->create_channel = gabble_media_factory_create_channel;
+  iface->ensure_channel = gabble_media_factory_ensure_channel;
 }
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index 301bfbc..f4a4d55 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -53,6 +53,7 @@ TWISTED_TESTS = \
 	jingle/test-outgoing-call-deprecated2.py \
 	jingle/test-outgoing-call-requestotron.py \
 	jingle/test-outgoing-call-rejected.py \
+	jingle/test-outgoing-call-ensure.py \
 	test-capabilities.py \
 	test-caps-cache.py \
 	test-caps-hash.py \
diff --git a/tests/twisted/jingle/test-outgoing-call-ensure.py b/tests/twisted/jingle/test-outgoing-call-ensure.py
new file mode 100644
index 0000000..2bb4446
--- /dev/null
+++ b/tests/twisted/jingle/test-outgoing-call-ensure.py
@@ -0,0 +1,215 @@
+
+"""
+Test making outgoing call using CreateChannel. This tests the happy scenario
+when the remote party accepts the call.
+"""
+
+from gabbletest import exec_test, make_result_iq, sync_stream
+from servicetest import make_channel_proxy, unwrap, tp_path_prefix, \
+        call_async, EventPattern
+from twisted.words.xish import domish
+import jingletest
+import gabbletest
+import dbus
+import time
+
+
+def test(q, bus, conn, stream):
+    jt = jingletest.JingleTest(stream, 'test at localhost', 'foo at bar.com/Foo')
+
+    # If we need to override remote caps, feats, codecs or caps,
+    # this is a good time to do it
+
+    # Connecting
+    conn.Connect()
+
+    q.expect('dbus-signal', signal='StatusChanged', args=[1, 1])
+
+    q.expect('stream-authenticated')
+    q.expect('dbus-signal', signal='PresenceUpdate',
+        args=[{1L: (0L, {u'available': {}})}])
+    q.expect('dbus-signal', signal='StatusChanged', args=[0, 1])
+
+    self_handle = conn.GetSelfHandle()
+
+    # We need remote end's presence for capabilities
+    jt.send_remote_presence()
+
+    # Gabble doesn't trust it, so makes a disco
+    event = q.expect('stream-iq', query_ns='http://jabber.org/protocol/disco#info',
+             to='foo at bar.com/Foo')
+
+    jt.send_remote_disco_reply(event.stanza)
+
+    # Force Gabble to process the caps before calling EnsureChannel
+    sync_stream(q, stream)
+
+    handle = conn.RequestHandles(1, [jt.remote_jid])[0]
+
+    requestotron = dbus.Interface(conn,
+            'org.freedesktop.Telepathy.Connection.Interface.Requests')
+
+
+    # Ensure a channel that doesn't exist yet.
+    call_async(q, requestotron, 'EnsureChannel',
+            { 'org.freedesktop.Telepathy.Channel.ChannelType':
+                'org.freedesktop.Telepathy.Channel.Type.StreamedMedia',
+              'org.freedesktop.Telepathy.Channel.TargetHandleType': 1,
+              'org.freedesktop.Telepathy.Channel.TargetHandle': handle,
+              })
+
+    ret, old_sig, new_sig = q.expect_many(
+        EventPattern('dbus-return', method='EnsureChannel'),
+        EventPattern('dbus-signal', signal='NewChannel'),
+        EventPattern('dbus-signal', signal='NewChannels'),
+        )
+
+    yours, path, props = ret.value
+
+    # this channel was created in response to our EnsureChannel call, so it
+    # should be ours.
+    assert yours, ret.value
+
+    sig_path, sig_ct, sig_ht, sig_h, sig_sh = old_sig.args
+
+    assert sig_path == path, (sig_path, path)
+    assert sig_ct == u'org.freedesktop.Telepathy.Channel.Type.StreamedMedia',\
+            sig_ct
+    assert sig_ht == 1, sig_ht      # HandleType = Contact
+    assert sig_h == handle, sig_h
+    assert sig_sh == 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] == path
+    emitted_props = new_sig.args[0][0][1]
+
+    assert emitted_props['org.freedesktop.Telepathy.Channel.ChannelType'] ==\
+            'org.freedesktop.Telepathy.Channel.Type.StreamedMedia'
+    assert emitted_props['org.freedesktop.Telepathy.Channel.'
+            'TargetHandleType'] == 1        # Contact
+    assert emitted_props['org.freedesktop.Telepathy.Channel.TargetHandle'] ==\
+            handle
+    assert emitted_props['org.freedesktop.Telepathy.Channel.TargetID'] ==\
+            'foo at bar.com', emitted_props
+    assert emitted_props['org.freedesktop.Telepathy.Channel.FUTURE.'
+            'Requested'] == True
+    assert emitted_props['org.freedesktop.Telepathy.Channel.FUTURE.'
+            'InitiatorHandle'] == self_handle
+    assert emitted_props['org.freedesktop.Telepathy.Channel.FUTURE.'
+            'InitiatorID'] == 'test at localhost'
+
+
+    # Now ensure a media channel with the same contact, and check it's the
+    # same.
+    call_async(q, requestotron, 'EnsureChannel',
+            { 'org.freedesktop.Telepathy.Channel.ChannelType':
+                'org.freedesktop.Telepathy.Channel.Type.StreamedMedia',
+              'org.freedesktop.Telepathy.Channel.TargetHandleType': 1,
+              'org.freedesktop.Telepathy.Channel.TargetHandle': handle,
+              })
+
+    event = q.expect('dbus-return', method='EnsureChannel')
+    yours2, path2, props2 = event.value
+
+    # We should have got back the same channel we created a page or so ago.
+    assert path == path2, (path, path2)
+    # It's not been created for this call, so Yours should be False.
+    assert not yours2
+
+    # Time passes ... afterwards we close the chan
+
+    chan = bus.get_object(conn.bus_name, path)
+    chan.Close()
+
+
+    # Now, create an anonymous channel with RequestChannel, add the other
+    # person to it with RequestStreams, then Ensure a media channel with that
+    # person.  We should get the anonymous channel back.
+    call_async(q, conn, 'RequestChannel',
+        'org.freedesktop.Telepathy.Channel.Type.StreamedMedia', 0, 0, True)
+
+    ret, old_sig, new_sig = q.expect_many(
+        EventPattern('dbus-return', method='RequestChannel'),
+        EventPattern('dbus-signal', signal='NewChannel'),
+        EventPattern('dbus-signal', signal='NewChannels'),
+        )
+
+    path = ret.value[0]
+    assert old_sig.args[0] == path, (old_sig.args[0], path)
+    assert old_sig.args[1] == u'org.freedesktop.Telepathy.Channel.Type.StreamedMedia',\
+            old_sig.args[1]
+    assert old_sig.args[2] == 0, sig.args[2]
+    assert old_sig.args[3] == 0, sig.args[3]
+    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] == path
+    emitted_props = new_sig.args[0][0][1]
+
+    assert emitted_props['org.freedesktop.Telepathy.Channel.ChannelType'] ==\
+            'org.freedesktop.Telepathy.Channel.Type.StreamedMedia'
+    assert emitted_props['org.freedesktop.Telepathy.Channel.'
+            'TargetHandleType'] == 0
+    assert emitted_props['org.freedesktop.Telepathy.Channel.TargetHandle'] ==\
+            0
+    assert emitted_props['org.freedesktop.Telepathy.Channel.TargetID'] == ''
+    assert emitted_props['org.freedesktop.Telepathy.Channel.FUTURE.'
+            'Requested'] == True
+    assert emitted_props['org.freedesktop.Telepathy.Channel.FUTURE.'
+            'InitiatorHandle'] == self_handle
+    assert emitted_props['org.freedesktop.Telepathy.Channel.FUTURE.'
+            'InitiatorID'] == 'test at localhost'
+
+    media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia')
+
+    # FIXME: Hack to make sure the disco info has been processed - we need to
+    # send Gabble some XML that will cause an event when processed, and
+    # wait for that event (until
+    # https://bugs.freedesktop.org/show_bug.cgi?id=15769 is fixed)
+    el = domish.Element(('jabber.client', 'presence'))
+    el['from'] = 'bob at example.com/Bar'
+    stream.send(el.toXml())
+    q.expect('dbus-signal', signal='PresenceUpdate')
+    # OK, now we can continue. End of hack
+
+    # Request streams with the other person.  This should make them the
+    # channel's "peer" property.
+    media_iface.RequestStreams(handle, [0]) # 0 == MEDIA_STREAM_TYPE_AUDIO
+
+    # Now, Ensuring a media channel with handle should yield the channel just
+    # created.
+
+    call_async(q, requestotron, 'EnsureChannel',
+            { 'org.freedesktop.Telepathy.Channel.ChannelType':
+                'org.freedesktop.Telepathy.Channel.Type.StreamedMedia',
+              'org.freedesktop.Telepathy.Channel.TargetHandleType': 1,
+              'org.freedesktop.Telepathy.Channel.TargetHandle': handle,
+              })
+
+    event = q.expect('dbus-return', method='EnsureChannel')
+    yours, path2, _ = event.value
+
+    # we should have got back the anonymous channel we got with requestchannel
+    # and called RequestStreams(handle) on.
+    assert path == path2, (path, path2)
+    # It's not been created for this call, so Yours should be False.
+    assert not yours
+
+    # Time passes ... afterwards we close the chan
+
+    chan = bus.get_object(conn.bus_name, path)
+    chan.Close()
+
+    conn.Disconnect()
+    q.expect('dbus-signal', signal='StatusChanged', args=[2, 1])
+
+    return True
+
+
+if __name__ == '__main__':
+    exec_test(test)
+
-- 
1.5.6.5




More information about the Telepathy-commits mailing list