Beispiel #1
0
def test(q, bus, conn1, conn2, stream1, stream2):
    # Connection 1
    conn1.Connect()
    q.expect('dbus-signal',
             signal='StatusChanged',
             args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])

    # Connection 1 blocks because the fake jabber server behind conn1 does not
    # proceed to the tls handshake. The second connection is independant and
    # should work.

    # Connection 2
    conn2.Connect()
    q.expect('dbus-signal',
             signal='StatusChanged',
             args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])
    q.expect('stream-authenticated')
    q.expect('dbus-signal',
             signal='PresencesChanged',
             args=[{
                 1: (cs.PRESENCE_AVAILABLE, 'available', '')
             }])
    q.expect('dbus-signal',
             signal='StatusChanged',
             args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    # Disconnection 2
    disconnect_conn(q, conn2, stream2)
Beispiel #2
0
def test(q, bus, conn, stream):
    event = q.expect('stream-iq',
                     to=None,
                     query_ns='vcard-temp',
                     query_name='vCard')

    acknowledge_iq(stream, event.stanza)

    handle = conn.get_contact_handle_sync('*****@*****.**')
    call_async(q, conn.Aliasing, 'RequestAliases', [handle])

    # First, Gabble sends a PEP query
    event = q.expect('stream-iq',
                     to='*****@*****.**',
                     iq_type='get',
                     query_ns='http://jabber.org/protocol/pubsub',
                     query_name='pubsub')

    # We disconnect too soon to get a reply
    disconnect_conn(q, conn, stream)

    # fd.o #31412 was that while the request pipeline was shutting down,
    # it would give the PEP query an error; the aliasing code would
    # respond by falling back to vCard via the request pipeline, which
    # was no longer there, *crash*.

    # check that Gabble hasn't crashed
    sync_dbus(bus, q, conn)
def test_disconnect_during_update_configuration(q, bus, conn, stream):
    """
    Test disconnecting while a pair of UpdateConfiguration requests are in
    flight: one waiting for the muc#owner form, and the other waiting for its
    changes to be acked.
    """
    def join_me_up_buttercup(muc):
        chan, _, _ = join_muc(q, bus, conn, stream, muc, affiliation='owner')
        # Gabble grabs the owner configuration form to see whether it's
        # possible to change the room description.
        owner_iq = q.expect('stream-iq', to=muc, iq_type='get',
            query_ns=ns.MUC_OWNER)
        handle_muc_owner_get_iq(stream, owner_iq.stanza)
        call_async(q, chan.RoomConfig1, 'UpdateConfiguration',
            {'Persistent': True})
        e = q.expect('stream-iq', to=muc, iq_type='get', query_ns=ns.MUC_OWNER)
        return chan, e

    ONE = '1@ttt'
    one, _ = join_me_up_buttercup(ONE)

    TWO = '2@ttt'
    two, e = join_me_up_buttercup(TWO)
    handle_muc_owner_get_iq(stream, e.stanza)
    q.expect('stream-iq', to=TWO, iq_type='set', query_ns=ns.MUC_OWNER)

    disconnect_conn(q, conn, stream, expected_after=[
        # Buh. We can't match on paths or on message serials … but we know
        # there are two of them!
        EventPattern('dbus-error', method='UpdateConfiguration',
            name=cs.CANCELLED),
        EventPattern('dbus-error', method='UpdateConfiguration',
            name=cs.CANCELLED),
        ])
Beispiel #4
0
 def test_too_slow(self, req1, req2, too_slow):
     """
     Regression test for a bug where if the channel was closed before the
     HTTP responses arrived, the responses finally arriving crashed Gabble.
     """
 
     # User gets bored, and ends the call.
     e = EventPattern('dbus-signal', signal='Closed',
         path=chan.object_path)
 
     if too_slow == TOO_SLOW_CLOSE:
         call_async(self.q, self.chan, 'Close', dbus_interface=cs.CHANNEL)
     elif too_slow == TOO_SLOW_REMOVE_SELF:
         self.chan.Hangup (0, "", "",
             dbus_interface=cs.CHANNEL_TYPE_CALL)
     elif too_slow == TOO_SLOW_DISCONNECT:
         disconnect_conn(q, conn, stream, [e])
 
         try:
             chan.GetMembers()
         except dbus.DBusException, e:
             # This should fail because the object's gone away, not because
             # Gabble's crashed.
             assert cs.DBUS_ERROR_UNKNOWN_METHOD == e.get_dbus_name(), \
                 "maybe Gabble crashed? %s" % e
         else:
             # Gabble will probably also crash in a moment, because the http
             # request callbacks will be called after the channel's meant to
             # have died, which will cause the channel to try to call
             # methods on the (finalized) connection.
             assert False, "the channel should be dead by now"
 
         return
def test(q, bus, conn1, conn2, stream1, stream2):
    # Connection 1
    conn1.Connect()
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])
    q.expect('stream-authenticated')
    q.expect('dbus-signal', signal='PresenceUpdate',
        args=[{1L: (0L, {u'available': {}})}])
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    # Connection 2
    conn2.Connect()
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])
    q.expect('stream-authenticated')
    q.expect('dbus-signal', signal='PresenceUpdate',
        args=[{1L: (0L, {u'available': {}})}])
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    # Disconnection 1
    disconnect_conn(q, conn1, stream1)

    # Disconnection 2
    disconnect_conn(q, conn2, stream2)
def run_cancel_test(q, bus, conn, stream):
    call_async (q, conn.Requests, 'CreateChannel',
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL,
          cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
          cs.TARGET_ID: muc,
          cs.CALL_INITIAL_AUDIO: True,
         }, byte_arrays = True)

    q.expect('stream-presence', to = muc + "/test")

    disconnect_conn(q, conn, stream)
Beispiel #7
0
def test_disconnect(q, bus, conn, stream):
    assertContains(cs.CONN_IFACE_POWER_SAVING,
                  conn.Get(cs.CONN, "Interfaces",
                           dbus_interface=cs.PROPERTIES_IFACE))

    assertEquals (False, conn.Get(cs.CONN_IFACE_POWER_SAVING,
                                  "PowerSavingActive",
                                  dbus_interface=cs.PROPERTIES_IFACE))

    call_async(q, conn.PowerSaving, 'SetPowerSaving', True)

    stanza = expect_command(q, 'enable')

    disconnect_conn(q, conn, stream)
def run_cancel_test(q, bus, conn, stream):
    call_async(q,
               conn.Requests,
               'CreateChannel', {
                   cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL,
                   cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
                   cs.TARGET_ID: muc,
                   cs.CALL_INITIAL_AUDIO: True,
               },
               byte_arrays=True)

    q.expect('stream-presence', to=muc + "/test")

    disconnect_conn(q, conn, stream)
def disconnect_before_disco(q, bus, conn, stream, server=None):
    iq_event, disco_event = q.expect_many(
        EventPattern('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard'),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, iq_event.stanza)

    # try to create a channel before the disco process is completed.
    # This creation will fail
    call_create(q, conn, server=server)

    # connection is disconnected. CreateChannel fails
    disconnect_conn(q, conn, stream, [
        EventPattern('dbus-error', method='CreateChannel', name=cs.DISCONNECTED)])
def test(q, bus, conn, stream, channel_type):
    jt = jingletest.JingleTest(stream, 'test@localhost', '[email protected]/Foo')

    # We intentionally DON'T set remote presence yet. Since Gabble is still
    # unsure whether to treat contact as offline for this purpose, it
    # will tentatively allow channel creation and contact handle addition

    handle = conn.RequestHandles(cs.HT_CONTACT, [jt.remote_jid])[0]

    if channel_type == cs.CHANNEL_TYPE_STREAMED_MEDIA:
        path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA,
            cs.HT_CONTACT, handle, True)
        media_iface = make_channel_proxy(conn, path,
            'Channel.Type.StreamedMedia')

    # So it turns out that the calls to RequestStreams and Disconnect could be
    # reordered while the first waits on the result of introspecting the
    # channel's object which is kicked off by making a proxy object for it,
    # whereas the connection proxy is long ago introspected. Isn't dbus-python
    # great? Syncing here forces that introspection to finish so we can rely on
    # the ordering of RequestStreams and Disconnect. Yay.
    sync_dbus(bus, q, conn)

    # Now we request streams before either <presence> or caps have arrived
    if channel_type == cs.CHANNEL_TYPE_STREAMED_MEDIA:
        call_async(q, media_iface, 'RequestStreams', handle,
            [cs.MEDIA_STREAM_TYPE_AUDIO])

        before_events, after_events = disconnect_conn(q, conn, stream,
            [EventPattern('dbus-error', method='RequestStreams')])

        # RequestStreams should now return NotAvailable
        assert before_events[0].error.get_dbus_name() == cs.NOT_AVAILABLE, \
            before_events[0].error
    else:
        call_async(q, conn.Requests, 'CreateChannel',
            { cs.CHANNEL_TYPE: channel_type,
              cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
              cs.TARGET_ID: jt.remote_jid,
              cs.CALL_INITIAL_AUDIO: True
            })

        before_events, after_events = disconnect_conn(q, conn, stream,
            [EventPattern('dbus-error', method='CreateChannel')])

        # CreateChannel should now return Disconnected
        assert before_events[0].error.get_dbus_name() == cs.DISCONNECTED, \
            before_events[0].error
def test_disconnect(q, bus, conn, stream):
    assertContains(
        cs.CONN_IFACE_POWER_SAVING,
        conn.Get(cs.CONN, "Interfaces", dbus_interface=cs.PROPERTIES_IFACE))

    assertEquals(
        False,
        conn.Get(cs.CONN_IFACE_POWER_SAVING,
                 "PowerSavingActive",
                 dbus_interface=cs.PROPERTIES_IFACE))

    call_async(q, conn.PowerSaving, 'SetPowerSaving', True)

    stanza = expect_command(q, 'enable')

    disconnect_conn(q, conn, stream)
def test(q, bus, conn, stream):
    expect_and_handle_get_vcard(q, stream)
    sync_stream(q, stream)

    call_async(
        q, conn.Avatars, 'SetAvatar', 'Guy.brush', 'image/x-mighty-pirate')
    expect_and_handle_get_vcard(q, stream)
    iq_event = q.expect(
        'stream-iq', iq_type='set', query_ns='vcard-temp', query_name='vCard')
    call_async(
        q, conn.Avatars, 'SetAvatar', 'LeChuck.brush', 'image/x-ghost-pirate')

    disconnect_conn(q, conn, stream)

    q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
    q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
    sync_dbus(bus, q, conn)
def test(q, bus, conn, stream):
    expect_and_handle_get_vcard(q, stream)
    sync_stream(q, stream)

    call_async(
        q, conn.Avatars, 'SetAvatar', b'Guy.brush', 'image/x-mighty-pirate')
    expect_and_handle_get_vcard(q, stream)
    iq_event = q.expect(
        'stream-iq', iq_type='set', query_ns='vcard-temp', query_name='vCard')
    call_async(
        q, conn.Avatars, 'SetAvatar', b'LeChuck.brush', 'image/x-ghost-pirate')

    disconnect_conn(q, conn, stream)

    q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
    q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
    sync_dbus(bus, q, conn)
Beispiel #14
0
def disconnect_before_disco(q, bus, conn, stream, server=None):
    iq_event, disco_event = q.expect_many(
        EventPattern('stream-iq',
                     to=None,
                     query_ns='vcard-temp',
                     query_name='vCard'),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, iq_event.stanza)

    # try to create a channel before the disco process is completed.
    # This creation will fail
    call_create(q, conn, server=server)

    # connection is disconnected. CreateChannel fails
    disconnect_conn(q, conn, stream, [
        EventPattern(
            'dbus-error', method='CreateChannel', name=cs.DISCONNECTED)
    ])
def test_disconnect_during_update_configuration(q, bus, conn, stream):
    """
    Test disconnecting while a pair of UpdateConfiguration requests are in
    flight: one waiting for the muc#owner form, and the other waiting for its
    changes to be acked.
    """
    def join_me_up_buttercup(muc):
        chan, _, _ = join_muc(q, bus, conn, stream, muc, affiliation='owner')
        # Gabble grabs the owner configuration form to see whether it's
        # possible to change the room description.
        owner_iq = q.expect('stream-iq',
                            to=muc,
                            iq_type='get',
                            query_ns=ns.MUC_OWNER)
        handle_muc_owner_get_iq(stream, owner_iq.stanza)
        call_async(q, chan.RoomConfig1, 'UpdateConfiguration',
                   {'Persistent': True})
        e = q.expect('stream-iq', to=muc, iq_type='get', query_ns=ns.MUC_OWNER)
        return chan, e

    ONE = '1@ttt'
    one, _ = join_me_up_buttercup(ONE)

    TWO = '2@ttt'
    two, e = join_me_up_buttercup(TWO)
    handle_muc_owner_get_iq(stream, e.stanza)
    q.expect('stream-iq', to=TWO, iq_type='set', query_ns=ns.MUC_OWNER)

    disconnect_conn(
        q,
        conn,
        stream,
        expected_after=[
            # Buh. We can't match on paths or on message serials … but we know
            # there are two of them!
            EventPattern('dbus-error',
                         method='UpdateConfiguration',
                         name=cs.CANCELLED),
            EventPattern('dbus-error',
                         method='UpdateConfiguration',
                         name=cs.CANCELLED),
        ])
def test(q, bus, conn1, conn2, stream1, stream2):
    # Connection 1
    conn1.Connect()
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])

    # Connection 1 blocks because the fake jabber server behind conn1 does not
    # proceed to the tls handshake. The second connection is independant and
    # should work.

    # Connection 2
    conn2.Connect()
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])
    q.expect('stream-authenticated')
    q.expect('dbus-signal', signal='PresenceUpdate',
        args=[{1L: (0L, {u'available': {}})}])
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    # Disconnection 2
    disconnect_conn(q, conn2, stream2)
def test(q, bus, conn, stream):
    event = q.expect('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard')

    acknowledge_iq(stream, event.stanza)

    handle = conn.RequestHandles(cs.HT_CONTACT, ['*****@*****.**'])[0]
    call_async(q, conn.Aliasing, 'RequestAliases', [handle])

    # First, Gabble sends a PEP query
    event = q.expect('stream-iq', to='*****@*****.**', iq_type='get',
        query_ns='http://jabber.org/protocol/pubsub', query_name='pubsub')

    # We disconnect too soon to get a reply
    disconnect_conn(q, conn, stream)

    # fd.o #31412 was that while the request pipeline was shutting down,
    # it would give the PEP query an error; the aliasing code would
    # respond by falling back to vCard via the request pipeline, which
    # was no longer there, *crash*.

    # check that Gabble hasn't crashed
    sync_dbus(bus, q, conn)
def test(q, bus, conn, stream):
    jt = jingletest.JingleTest(stream, 'test@localhost', '[email protected]/Foo')

    conn.Connect()

    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])

    q.expect('stream-authenticated')
    q.expect('dbus-signal', signal='PresenceUpdate',
        args=[{1L: (0L, {u'available': {}})}])
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    # We intentionally DON'T set remote presence yet. Since Gabble is still
    # unsure whether to treat contact as offline for this purpose, it
    # will tentatively allow channel creation and contact handle addition

    handle = conn.RequestHandles(cs.HT_CONTACT, [jt.remote_jid])[0]

    path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT,
        handle, True)
    media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia')

    # So it turns out that the calls to RequestStreams and Disconnect could be
    # reordered while the first waits on the result of introspecting the
    # channel's object which is kicked off by making a proxy object for it,
    # whereas the connection proxy is long ago introspected. Isn't dbus-python
    # great? Syncing here forces that introspection to finish so we can rely on
    # the ordering of RequestStreams and Disconnect. Yay.
    sync_dbus(bus, q, conn)

    # Now we request streams before either <presence> or caps have arrived
    call_async(q, media_iface, 'RequestStreams', handle,
        [cs.MEDIA_STREAM_TYPE_AUDIO])

    event = disconnect_conn(q, conn, stream,
        [EventPattern('dbus-error', method='RequestStreams')])[0]

    # RequestStreams should now return NotAvailable
    assert event.error.get_dbus_name() == cs.NOT_AVAILABLE, event.error
Beispiel #19
0
def test(q, bus, conn, stream):
    event = q.expect('stream-iq', to='localhost',
                query_ns='http://jabber.org/protocol/disco#items')

    result = make_result_iq(stream, event.stanza)
    item = result.firstChildElement().addElement('item')
    item['jid'] = 'conf.localhost'
    stream.send(result)

    event = q.expect('stream-iq', to='conf.localhost',
        query_ns='http://jabber.org/protocol/disco#info')
    result = make_result_iq(stream, event.stanza)
    feature = result.firstChildElement().addElement('feature')
    feature['var'] = 'http://jabber.org/protocol/muc'
    identity = result.firstChildElement().addElement('identity')
    identity['category'] = 'conference'
    identity['name'] = 'conference service'
    identity['type'] = 'text'
    stream.send(result)

    # Make sure the stream has been processed
    sync_stream(q, stream)

    properties = conn.GetAll(
            tp_name_prefix + '.Connection.Interface.Requests',
            dbus_interface=dbus.PROPERTIES_IFACE)
    assert properties.get('Channels') == [], properties['Channels']
    assert ({tp_name_prefix + '.Channel.ChannelType':
                tp_name_prefix + '.Channel.Type.RoomList',
             tp_name_prefix + '.Channel.TargetHandleType': 0,
             },
             [tp_name_prefix + '.Channel.Type.RoomList.Server'],
             ) in properties.get('RequestableChannelClasses'),\
                     properties['RequestableChannelClasses']

    call_async(q, conn, 'RequestChannel',
        tp_name_prefix + '.Channel.Type.RoomList', 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'),
        )

    bus = dbus.SessionBus()
    path1 = ret.value[0]
    chan = bus.get_object(conn.bus_name, path1)

    assert new_sig.args[0][0][0] == path1

    props = new_sig.args[0][0][1]
    assert props[tp_name_prefix + '.Channel.ChannelType'] ==\
            tp_name_prefix + '.Channel.Type.RoomList'
    assert props[tp_name_prefix + '.Channel.TargetHandleType'] == 0
    assert props[tp_name_prefix + '.Channel.TargetHandle'] == 0
    assert props[tp_name_prefix + '.Channel.TargetID'] == ''
    assert props[tp_name_prefix + '.Channel.Requested'] == True
    assert props[tp_name_prefix + '.Channel.InitiatorHandle'] \
            == conn.GetSelfHandle()
    assert props[tp_name_prefix + '.Channel.InitiatorID'] \
            == 'test@localhost'
    assert props[tp_name_prefix + '.Channel.Type.RoomList.Server'] == \
            'conf.localhost'

    assert old_sig.args[0] == path1
    assert old_sig.args[1] == tp_name_prefix + '.Channel.Type.RoomList'
    assert old_sig.args[2] == 0     # handle type
    assert old_sig.args[3] == 0     # handle
    assert old_sig.args[4] == 1     # suppress handler

    # Exercise basic Channel Properties from spec 0.17.7
    channel_props = chan.GetAll(
            tp_name_prefix + '.Channel',
            dbus_interface=dbus.PROPERTIES_IFACE)
    assert channel_props.get('TargetHandle') == 0,\
            channel_props.get('TargetHandle')
    assert channel_props['TargetID'] == '', channel_props
    assert channel_props.get('TargetHandleType') == 0,\
            channel_props.get('TargetHandleType')
    assert channel_props.get('ChannelType') == \
            tp_name_prefix + '.Channel.Type.RoomList',\
            channel_props.get('ChannelType')
    assert channel_props['Requested'] == True
    assert channel_props['InitiatorID'] == 'test@localhost'
    assert channel_props['InitiatorHandle'] == conn.GetSelfHandle()

    assert chan.Get(
            tp_name_prefix + '.Channel.Type.RoomList', 'Server',
            dbus_interface=dbus.PROPERTIES_IFACE) == \
                    'conf.localhost'

    # FIXME: actually list the rooms!

    call_async(q, conn.Requests, 'CreateChannel',
            { tp_name_prefix + '.Channel.ChannelType':
                tp_name_prefix + '.Channel.Type.RoomList',
              tp_name_prefix + '.Channel.TargetHandleType': 0,
              tp_name_prefix + '.Channel.Type.RoomList.Server':
                'conference.example.net',
              })

    ret, old_sig, new_sig = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
        )
    path2 = ret.value[0]
    chan = bus.get_object(conn.bus_name, path2)

    props = ret.value[1]
    assert props[tp_name_prefix + '.Channel.ChannelType'] ==\
            tp_name_prefix + '.Channel.Type.RoomList'
    assert props[tp_name_prefix + '.Channel.TargetHandleType'] == 0
    assert props[tp_name_prefix + '.Channel.TargetHandle'] == 0
    assert props[tp_name_prefix + '.Channel.TargetID'] == ''
    assert props[tp_name_prefix + '.Channel.Requested'] == True
    assert props[tp_name_prefix + '.Channel.InitiatorHandle'] \
            == conn.GetSelfHandle()
    assert props[tp_name_prefix + '.Channel.InitiatorID'] \
            == 'test@localhost'
    assert props[tp_name_prefix + '.Channel.Type.RoomList.Server'] == \
            'conference.example.net'

    assert new_sig.args[0][0][0] == path2
    assert new_sig.args[0][0][1] == props

    assert old_sig.args[0] == path2
    assert old_sig.args[1] == tp_name_prefix + '.Channel.Type.RoomList'
    assert old_sig.args[2] == 0     # handle type
    assert old_sig.args[3] == 0     # handle
    assert old_sig.args[4] == 1     # suppress handler

    assert chan.Get(
            tp_name_prefix + '.Channel.Type.RoomList', 'Server',
            dbus_interface=dbus.PROPERTIES_IFACE) == \
                    'conference.example.net'

    # FIXME: actually list the rooms!

    call_async(q, conn.Requests, 'EnsureChannel',
            { tp_name_prefix + '.Channel.ChannelType':
                tp_name_prefix + '.Channel.Type.RoomList',
              tp_name_prefix + '.Channel.TargetHandleType': 0,
              tp_name_prefix + '.Channel.Type.RoomList.Server':
                'conference.example.net',
              })

    ret = q.expect('dbus-return', method='EnsureChannel')
    yours, ensured_path, ensured_props = ret.value

    assert not yours
    assert ensured_path == path2, (ensured_path, path2)

    disconnect_conn(q, conn, stream, [
    EventPattern('dbus-signal', signal='Closed', path=path1),
    EventPattern('dbus-signal', signal='Closed', path=path2),
    EventPattern('dbus-signal', signal='ChannelClosed', args=[path1]),
    EventPattern('dbus-signal', signal='ChannelClosed', args=[path2])])
Beispiel #20
0
def test(q, bus, conn, stream):
    # we don't yet know we have PEP
    assertEquals(
        0,
        conn.Get(cs.CONN_IFACE_LOCATION,
                 "SupportedLocationFeatures",
                 dbus_interface=cs.PROPERTIES_IFACE))

    conn.Connect()

    # discard activities request and status change
    q.expect_many(
        EventPattern('stream-iq', iq_type='set', query_ns=ns.PUBSUB),
        EventPattern('dbus-signal',
                     signal='StatusChanged',
                     args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]),
    )

    # we now know we have PEP
    assertEquals(
        cs.LOCATION_FEATURE_CAN_SET,
        conn.Get(cs.CONN_IFACE_LOCATION,
                 "SupportedLocationFeatures",
                 dbus_interface=cs.PROPERTIES_IFACE))

    # check location properties

    access_control_types = conn.Get(cs.CONN_IFACE_LOCATION,
                                    "LocationAccessControlTypes",
                                    dbus_interface=cs.PROPERTIES_IFACE)
    # only one access control is implemented in Gabble at the moment:
    assert len(access_control_types) == 1, access_control_types
    assert access_control_types[0] == \
        Rich_Presence_Access_Control_Type_Publish_List

    access_control = conn.Get(cs.CONN_IFACE_LOCATION,
                              "LocationAccessControl",
                              dbus_interface=cs.PROPERTIES_IFACE)
    assert len(access_control) == 2, access_control
    assert access_control[0] == \
        Rich_Presence_Access_Control_Type_Publish_List

    properties = conn.GetAll(cs.CONN_IFACE_LOCATION,
                             dbus_interface=cs.PROPERTIES_IFACE)

    assert properties.get('LocationAccessControlTypes') == access_control_types
    assert properties.get('LocationAccessControl') == access_control

    # Test setting the properties

    # Enum out of range
    bad_access_control = dbus.Struct(
        [dbus.UInt32(99), dbus.UInt32(0, variant_level=1)],
        signature=dbus.Signature('uv'))
    try:
        conn.Set(cs.CONN_IFACE_LOCATION,
                 'LocationAccessControl',
                 bad_access_control,
                 dbus_interface=cs.PROPERTIES_IFACE)
    except dbus.DBusException as e:
        pass
    else:
        assert False, "Should have had an error!"

    # Bad type
    bad_access_control = dbus.String("This should not be a string")
    try:
        conn.Set(cs.CONN_IFACE_LOCATION,
                 'LocationAccessControl',
                 bad_access_control,
                 dbus_interface=cs.PROPERTIES_IFACE)
    except dbus.DBusException as e:
        assert e.get_dbus_name() == cs.INVALID_ARGUMENT, e.get_dbus_name()
    else:
        assert False, "Should have had an error!"

    # Bad type
    bad_access_control = dbus.Struct([
        dbus.String("bad"),
        dbus.String("!"),
        dbus.UInt32(0, variant_level=1)
    ],
                                     signature=dbus.Signature('ssv'))
    try:
        conn.Set(cs.CONN_IFACE_LOCATION,
                 'LocationAccessControl',
                 bad_access_control,
                 dbus_interface=cs.PROPERTIES_IFACE)
    except dbus.DBusException as e:
        assert e.get_dbus_name() == cs.INVALID_ARGUMENT, e.get_dbus_name()
    else:
        assert False, "Should have had an error!"

    # Correct
    conn.Set(cs.CONN_IFACE_LOCATION,
             'LocationAccessControl',
             access_control,
             dbus_interface=cs.PROPERTIES_IFACE)

    # LocationAccessControlTypes is read-only, check Gabble return the
    # PermissionDenied error
    try:
        conn.Set(cs.CONN_IFACE_LOCATION,
                 'LocationAccessControlTypes',
                 access_control_types,
                 dbus_interface=cs.PROPERTIES_IFACE)
    except dbus.DBusException as e:
        assert e.get_dbus_name() == cs.PERMISSION_DENIED, e.get_dbus_name()
    else:
        assert False, "Should have had an error!"

    date = dbus.Int64(time.time())
    date_str = datetime.datetime.utcfromtimestamp(date).strftime(
        '%FT%H:%M:%SZ')

    # set a Location
    call_async(
        q,
        conn.Location,
        'SetLocation',
        {
            'lat': dbus.Double(0.0, variant_level=1),
            'lon': 0.0,
            'language': 'en',
            'timestamp': date,
            'country': 'Congo',
            'accuracy': 1.4,
            # Gabble silently ignores unknown keys
            'badger': 'mushroom'
        })

    geoloc_iq_set_event = EventPattern(
        'stream-iq',
        predicate=lambda x: xpath.queryForNodes(
            "/iq/pubsub/publish/item/geoloc", x.stanza))

    event = q.expect_many(geoloc_iq_set_event)[0]
    geoloc = xpath.queryForNodes("/iq/pubsub/publish/item/geoloc",
                                 event.stanza)[0]
    assertEquals(geoloc.getAttribute((ns.XML, 'lang')), 'en')
    lon = xpath.queryForNodes('/geoloc/lon', geoloc)[0]
    assertEquals(float(str(lon)), 0.0)
    lat = xpath.queryForNodes('/geoloc/lat', geoloc)[0]
    assertEquals(float(str(lat)), 0.0)
    timestamp = xpath.queryForNodes('/geoloc/timestamp', geoloc)[0]
    assertEquals(str(timestamp), date_str)
    country = xpath.queryForNodes('/geoloc/country', geoloc)[0]
    assertEquals(str(country), 'Congo')
    lat = xpath.queryForNodes('/geoloc/accuracy', geoloc)[0]
    assertEquals(float(str(lat)), 1.4)

    acknowledge_iq(stream, event.stanza)
    q.expect('dbus-return', method='SetLocation')

    # Server refuses to set Location
    call_async(q, conn.Location, 'SetLocation', {'lat': 0.0, 'lon': 0.0})

    geoloc_iq_set_event = EventPattern(
        'stream-iq',
        predicate=lambda x: xpath.queryForNodes(
            "/iq/pubsub/publish/item/geoloc", x.stanza))
    event = q.expect_many(geoloc_iq_set_event)[0]

    send_error_reply(stream, event.stanza)
    q.expect('dbus-error', method='SetLocation')

    # Request Bob's location
    bob_handle = conn.get_contact_handle_sync('*****@*****.**')

    # Gabble should not send a pubsub query. The point of PEP is that we don't
    # have to do this.
    pubsub_get_pattern = EventPattern('stream-iq',
                                      iq_type='get',
                                      query_ns=ns.PUBSUB)
    q.forbid_events([pubsub_get_pattern])

    location = get_location(conn, bob_handle)
    # Location isn't known yet
    assertEquals(None, location)

    # Sync the XMPP stream to ensure Gabble hasn't sent a query.
    sync_stream(q, stream)

    # Bob updates his location
    message = elem('message', from_='*****@*****.**')(
        elem((ns.PUBSUB_EVENT), 'event')(
            elem('items', node=ns.GEOLOC)(
                elem('item', id='12345')(
                    elem(ns.GEOLOC, 'geoloc', attrs={'xml:lang': 'en'})(
                        elem('lat')(u'1.25'),
                        elem('lon')(u'5.5'),
                        elem('country')(u'Belgium'),
                        elem('accuracy')(u'2.3'),
                        elem('timestamp')(date_str),
                        # invalid element, will be ignored by Gabble
                        elem('badger')(u'mushroom'),
                    )))))
    stream.send(message)

    update_event = q.expect('dbus-signal', signal='LocationUpdated')

    handle, location = update_event.args
    assertEquals(bob_handle, handle)

    assertLength(6, location)
    assertEquals(location['language'], 'en')
    assertEquals(location['lat'], 1.25)
    assertEquals(location['lon'], 5.5)
    assertEquals(location['country'], 'Belgium')
    assertEquals(location['accuracy'], 2.3)
    assertEquals(location['timestamp'], date)

    # Get location again; Gabble should return the cached location
    loc = get_location(conn, bob_handle)
    assertEquals(loc, location)

    charles_handle = conn.get_contact_handle_sync('*****@*****.**')

    # check that Contacts interface supports location
    attributes = conn.Contacts.GetContactAttributes(
        [bob_handle, charles_handle], [cs.CONN_IFACE_LOCATION], False)
    assertLength(2, attributes)
    assertContains(bob_handle, attributes)
    assertContains(charles_handle, attributes)

    assertEquals(
        {
            cs.CONN_IFACE_LOCATION + '/location': location,
            cs.CONN + '/contact-id': '*****@*****.**'
        }, attributes[bob_handle])

    assertEquals({cs.CONN + '/contact-id': '*****@*****.**'},
                 attributes[charles_handle])

    # Try to set our location by passing a valid with an invalid type (lat is
    # supposed to be a double)

    q.forbid_events([geoloc_iq_set_event])

    try:
        conn.Location.SetLocation({'lat': 'pony'})
    except dbus.DBusException as e:
        assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
    else:
        assert False

    # Bob updates his location again
    message = elem('message', from_='*****@*****.**')(elem(
        (ns.PUBSUB_EVENT),
        'event')(elem('items', node=ns.GEOLOC)(elem('item', id='12345')(elem(
            ns.GEOLOC, 'geoloc')(elem('country')(u'France'))))))
    stream.send(message)

    update_event = q.expect('dbus-signal', signal='LocationUpdated')
    handle, location = update_event.args
    assertEquals(handle, bob_handle)
    assertLength(1, location)
    assertEquals(location['country'], 'France')

    # Now we test explicitly retrieving Bob's location, so we should not forbid
    # such queries. :)
    q.unforbid_events([pubsub_get_pattern])

    call_async(q, conn.Location, 'RequestLocation', bob_handle)
    e = q.expect('stream-iq',
                 iq_type='get',
                 query_ns=ns.PUBSUB,
                 to='*****@*****.**')

    # Hey, while we weren't looking Bob moved abroad!
    result = make_result_iq(stream, e.stanza)
    result['from'] = '*****@*****.**'
    pubsub_node = result.firstChildElement()
    pubsub_node.addChild(
        elem('items', node=ns.GEOLOC)(elem('item', id='12345')(elem(
            ns.GEOLOC, 'geoloc')(elem('country')(u'Chad')))))
    stream.send(result)

    ret = q.expect('dbus-return', method='RequestLocation')
    location, = ret.value
    assertLength(1, location)
    assertEquals(location['country'], 'Chad')

    # Let's ask again; this time Bob's server hates us for some reason.
    call_async(q, conn.Location, 'RequestLocation', bob_handle)
    e = q.expect('stream-iq',
                 iq_type='get',
                 query_ns=ns.PUBSUB,
                 to='*****@*****.**')
    send_error_reply(stream, e.stanza,
                     elem('error', type='auth')(elem(ns.STANZA, 'forbidden')))
    e = q.expect('dbus-error', method='RequestLocation')
    assertEquals(cs.PERMISSION_DENIED, e.name)

    # FIXME: maybe we should check that the cache gets invalidated in this
    # case? We should also test whether or not the cache is invalidated
    # properly if the contact clears their PEP node.

    # Let's ask a final time, and disconnect while we're doing so, to make sure
    # this doesn't break Gabble or Wocky.
    call_async(q, conn.Location, 'RequestLocation', bob_handle)
    e = q.expect('stream-iq',
                 iq_type='get',
                 query_ns=ns.PUBSUB,
                 to='*****@*****.**')
    # Tasty argument unpacking. disconnect_conn returns two lists, one for
    # expeced_before=[] and one for expected_after=[...]
    _, (e, ) = disconnect_conn(
        q,
        conn,
        stream,
        expected_after=[EventPattern('dbus-error', method='RequestLocation')])
    assertEquals(cs.CANCELLED, e.name)
def test(q, bus, conn, stream, bytestream_cls,
        address_type, access_control, access_control_param):
    if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]:
        # disable SOCKS5 relay tests because proxy can't be used with muc
        # contacts atm
        return

    if access_control == cs.SOCKET_ACCESS_CONTROL_CREDENTIALS:
        print "Skip Socket_Access_Control_Credentials (fdo #45445)"
        return

    iq_event, disco_event = q.expect_many(
        EventPattern('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard'),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, iq_event.stanza)

    announce_socks5_proxy(q, stream, disco_event.stanza)

    # join the muc
    call_async(q, conn.Requests, 'CreateChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.TARGET_ID: '*****@*****.**'})

    q.expect_many(
        EventPattern('dbus-signal', signal='MembersChangedDetailed',
            predicate=lambda e:
                e.args[0] == [] and         # added
                e.args[1] == [] and         # removed
                e.args[2] == [] and         # local pending
                len(e.args[3]) == 1 and     # remote pending
                e.args[4].get('actor', 0) == 0 and
                e.args[4].get('change-reason', 0) == 0 and
                e.args[4]['contact-ids'][e.args[3][0]] == '[email protected]/test'),
        EventPattern('stream-presence', to='[email protected]/test'))

    # Send presence for other member of room.
    stream.send(make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob'))

    # Send presence for own membership of room.
    stream.send(make_muc_presence('none', 'participant', '*****@*****.**', 'test'))

    event = q.expect('dbus-signal', signal='MembersChangedDetailed',
            predicate=lambda e:
                len(e.args[0]) == 2 and     # added
                e.args[1] == [] and         # removed
                e.args[2] == [] and         # local pending
                e.args[3] == [] and         # remote pending
                e.args[4].get('actor', 0) == 0 and
                e.args[4].get('change-reason', 0) == 0 and
                set([e.args[4]['contact-ids'][h] for h in e.args[0]]) ==
                set(['[email protected]/test', '[email protected]/bob']))

    for h in event.args[0]:
        if event.args[4]['contact-ids'][h] == '[email protected]/bob':
            bob_handle = h

    event = q.expect('dbus-return', method='CreateChannel')

    # Bob offers a stream tube
    stream_tube_id = 666
    presence = make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob')
    tubes = presence.addElement((ns.TUBES, 'tubes'))
    tube = tubes.addElement((None, 'tube'))
    tube['type'] = 'stream'
    tube['service'] = 'echo'
    tube['id'] = str(stream_tube_id)
    parameters = tube.addElement((None, 'parameters'))
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 's'
    parameter['type'] = 'str'
    parameter.addContent('hello')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'ay'
    parameter['type'] = 'bytes'
    parameter.addContent('aGVsbG8=')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'u'
    parameter['type'] = 'uint'
    parameter.addContent('123')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'i'
    parameter['type'] = 'int'
    parameter.addContent('-123')

    stream.send(presence)

    # text channel
    new_event = q.expect('dbus-signal', signal='NewChannels')

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT

    def new_chan_predicate(e):
        path, props = e.args[0][0]
        return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE

    # tube channel is announced
    new_event = q.expect('dbus-signal', signal='NewChannels',
                         predicate=new_chan_predicate)

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
    assert props[cs.INITIATOR_HANDLE] == bob_handle
    assert props[cs.INITIATOR_ID] == '[email protected]/bob'
    assertSameSets([cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE],
            props[cs.INTERFACES])
    assert props[cs.REQUESTED] == False
    assert props[cs.TARGET_ID] == '*****@*****.**'
    assert props[cs.STREAM_TUBE_SERVICE] == 'echo'
    assert props[cs.TUBE_PARAMETERS] == {'s': 'hello', 'ay': 'hello', 'u': 123, 'i': -123}
    assert access_control in \
            props[cs.STREAM_TUBE_SUPPORTED_SOCKET_TYPES][address_type]

    tube_chan = bus.get_object(conn.bus_name, path)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE,
        byte_arrays=True)
    tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
    assert tube_props['Parameters'] == sample_parameters
    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING

    # Accept the tube
    call_async(q, tube_iface, 'Accept',
        address_type, access_control, access_control_param, byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='Accept'),
        EventPattern('dbus-signal', signal='TubeChannelStateChanged',
            args=[2]))

    address = accept_return_event.value[0]

    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    protocol = socket_event.protocol
    protocol.sendData("hello initiator")

    def accept_tube_si_connection():
        bytestream, profile = create_from_si_offer(stream, q, bytestream_cls, si_event.stanza,
                '[email protected]/test')

        assert profile == ns.TUBES

        muc_stream_node = xpath.queryForNodes('/iq/si/muc-stream[@xmlns="%s"]' %
            ns.TUBES, si_event.stanza)[0]
        assert muc_stream_node is not None
        assert muc_stream_node['tube'] == str(stream_tube_id)

        # set the real jid of the target as 'to' because the XMPP server changes
        # it when delivering the IQ
        result, si = bytestream.create_si_reply(si_event.stanza, 'test@localhost/Resource')
        si.addElement((ns.TUBES, 'tube'))
        stream.send(result)

        bytestream.wait_bytestream_open()
        return bytestream

    bytestream = accept_tube_si_connection()

    binary = bytestream.get_data()
    assert binary == 'hello initiator'

    # reply on the socket
    bytestream.send_data('hi joiner!')

    q.expect('socket-data', protocol=protocol, data="hi joiner!")

    # peer closes the bytestream
    bytestream.close()
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_LOST, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    # bytestream is refused
    send_error_reply(stream, si_event.stanza)
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_REFUSED, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    protocol = socket_event.protocol
    bytestream = accept_tube_si_connection()

    # disconnect local socket
    protocol.transport.loseConnection()
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CANCELLED, e.args[1])

    # OK, we're done
    disconnect_conn(q, conn, stream)
Beispiel #22
0
def test(q, bus, conn, stream):
    event = q.expect('stream-iq',
                     to='localhost',
                     query_ns='http://jabber.org/protocol/disco#items')

    result = make_result_iq(stream, event.stanza)
    item = result.firstChildElement().addElement('item')
    item['jid'] = 'conf.localhost'
    stream.send(result)

    event = q.expect('stream-iq',
                     to='conf.localhost',
                     query_ns='http://jabber.org/protocol/disco#info')
    result = make_result_iq(stream, event.stanza)
    feature = result.firstChildElement().addElement('feature')
    feature['var'] = 'http://jabber.org/protocol/muc'
    identity = result.firstChildElement().addElement('identity')
    identity['category'] = 'conference'
    identity['name'] = 'conference service'
    identity['type'] = 'text'
    stream.send(result)

    # Make sure the stream has been processed
    sync_stream(q, stream)

    properties = conn.Properties.GetAll(cs.CONN_IFACE_REQUESTS)
    assert properties.get('Channels') == [], properties['Channels']
    assert ({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_ROOM_LIST,
              cs.TARGET_HANDLE_TYPE: cs.HT_NONE,
             },
             [cs.CHANNEL_TYPE_ROOM_LIST + '.Server'],
             ) in properties.get('RequestableChannelClasses'),\
                     properties['RequestableChannelClasses']

    # FIXME: actually list the rooms!

    call_async(
        q, conn.Requests, 'CreateChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_ROOM_LIST,
            cs.TARGET_HANDLE_TYPE: cs.HT_NONE,
            cs.CHANNEL_TYPE_ROOM_LIST + '.Server': 'conference.example.net',
        })

    ret, sig = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
    )
    path2 = ret.value[0]
    chan = bus.get_object(conn.bus_name, path2)

    props = ret.value[1]
    assertEquals(cs.CHANNEL_TYPE_ROOM_LIST, props[cs.CHANNEL_TYPE])
    assertEquals(cs.HT_NONE, props[cs.TARGET_HANDLE_TYPE])
    assertEquals(0, props[cs.TARGET_HANDLE])
    assertEquals('', props[cs.TARGET_ID])
    assertEquals(True, props[cs.REQUESTED])
    assertEquals(conn.Properties.Get(cs.CONN, "SelfHandle"),
                 props[cs.INITIATOR_HANDLE])
    assertEquals('test@localhost', props[cs.INITIATOR_ID])
    assertEquals('conference.example.net',
                 props[cs.CHANNEL_TYPE_ROOM_LIST + '.Server'])

    assert sig.args[0][0][0] == path2
    assert sig.args[0][0][1] == props

    assert chan.Get(cs.CHANNEL_TYPE_ROOM_LIST, 'Server',
            dbus_interface=dbus.PROPERTIES_IFACE) == \
                    'conference.example.net'

    # FIXME: actually list the rooms!

    call_async(
        q, conn.Requests, 'EnsureChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_ROOM_LIST,
            cs.TARGET_HANDLE_TYPE: cs.HT_NONE,
            cs.CHANNEL_TYPE_ROOM_LIST + '.Server': 'conference.example.net',
        })

    ret = q.expect('dbus-return', method='EnsureChannel')
    yours, ensured_path, ensured_props = ret.value

    assert not yours
    assert ensured_path == path2, (ensured_path, path2)

    disconnect_conn(q, conn, stream, [
        EventPattern('dbus-signal', signal='Closed', path=path2),
        EventPattern('dbus-signal', signal='ChannelClosed', args=[path2])
    ])
def test(q, bus, conn, stream, incoming=True, too_slow=None, use_call=False):
    jt = jingletest.JingleTest(stream, 'test@localhost', '[email protected]/Foo')

    if use_call:
        # wjt only updated just about enough of this test for Call to check for
        # one specific crash, not to verify that it all works...
        assert incoming
        assert too_slow in [TOO_SLOW_CLOSE, TOO_SLOW_DISCONNECT]

        # Tell Gabble we want to use Call.
        conn.ContactCapabilities.UpdateCapabilities([
            (cs.CLIENT + ".CallHandler", [
                { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL,
                    cs.CALL_INITIAL_AUDIO: True},
                { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL,
                    cs.CALL_INITIAL_VIDEO: True},
                ], [
                    cs.CHANNEL_TYPE_CALL + '/gtalk-p2p',
                    cs.CHANNEL_TYPE_CALL + '/ice-udp',
                    cs.CHANNEL_TYPE_CALL + '/video/h264',
                ]),
            ])

    # See: http://code.google.com/apis/talk/jep_extensions/jingleinfo.html
    ji_event = q.expect('stream-iq', query_ns='google:jingleinfo',
                to='test@localhost')

    # Regression test for a bug where Gabble would crash if it disconnected
    # before receiving a reply to the google:jingleinfo query.
    if too_slow == TOO_SLOW_DISCONNECT_IMMEDIATELY:
        disconnect_conn(q, conn, stream, [])
        return

    listen_port = listen_http(q, 0)

    jingleinfo = make_result_iq(stream, ji_event.stanza)
    stun = jingleinfo.firstChildElement().addElement('stun')
    server = stun.addElement('server')
    server['host'] = 'resolves-to-1.2.3.4'
    server['udp'] = '12345'

    expected_stun_server = '1.2.3.4'
    expected_stun_port = 12345

    # This bit is undocumented... but it has the same format as what we get
    # from Google Talk servers:
    # <iq to="censored" from="censored" id="73930208084" type="result">
    #   <query xmlns="google:jingleinfo">
    #     <stun>
    #       <server host="stun.l.google.com" udp="19302"/>
    #       <server host="stun4.l.google.com" udp="19302"/>
    #       <server host="stun3.l.google.com" udp="19302"/>
    #       <server host="stun1.l.google.com" udp="19302"/>
    #       <server host="stun2.l.google.com" udp="19302"/>
    #     </stun>
    #     <relay>
    #       <token>censored</token>
    #       <server host="relay.google.com" udp="19295" tcp="19294"
    #         tcpssl="443"/>
    #     </relay>
    #   </query>
    # </iq>
    relay = jingleinfo.firstChildElement().addElement('relay')
    relay.addElement('token', content='jingle all the way')
    server = relay.addElement('server')
    server['host'] = '127.0.0.1'
    server['udp'] = '11111'
    server['tcp'] = '22222'
    server['tcpssl'] = '443'
    # The special regression-test build of Gabble parses this attribute,
    # because we can't listen on port 80
    server['gabble-test-http-port'] = str(listen_port.getHost().port)
    stream.send(jingleinfo)
    jingleinfo = None

    # Spoof some jingle info. This is a regression test for
    # <https://bugs.freedesktop.org/show_bug.cgi?id=34048>. We assert that
    # Gabble has ignored this stuff later.
    iq = IQ(stream, 'set')
    iq['from'] = "*****@*****.**"
    query = iq.addElement((ns.GOOGLE_JINGLE_INFO, "query"))

    stun = query.addElement('stun')
    server = stun.addElement('server')
    server['host'] = '6.6.6.6'
    server['udp'] = '6666'

    relay = query.addElement('relay')
    relay.addElement('token', content='mwohahahahaha')
    server = relay.addElement('server')
    server['host'] = '127.0.0.1'
    server['udp'] = '666'
    server['tcp'] = '999'
    server['tcpssl'] = '666'

    stream.send(iq)

    # 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='[email protected]/Foo')

    jt.send_remote_disco_reply(event.stanza)

    # Force Gabble to process the capabilities
    sync_stream(q, stream)

    remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["[email protected]/Foo"])[0]
    self_handle = conn.GetSelfHandle()
    req_pattern = EventPattern('http-request', method='GET', path='/create_session')

    if incoming:
        # Remote end calls us
        jt.incoming_call()

        if use_call:
            def looks_like_a_call_to_me(event):
                channels, = event.args
                path, props = channels[0]
                return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_CALL
            new_channels = q.expect('dbus-signal', signal='NewChannels',
                predicate=looks_like_a_call_to_me)

            path = new_channels.args[0][0][0]
            media_chan = bus.get_object(conn.bus_name, path)
        else:
            # FIXME: these signals are not observable by real clients, since they
            #        happen before NewChannels.
            # The caller is in members
            # We're pending because of remote_handle
            mc, _, e = q.expect_many(
                EventPattern('dbus-signal', signal='MembersChanged',
                     args=[u'', [remote_handle], [], [], [], 0, 0]),
                EventPattern('dbus-signal', signal='MembersChanged',
                     args=[u'', [], [], [self_handle], [], remote_handle,
                           cs.GC_REASON_INVITED]),
                EventPattern('dbus-signal', signal='NewSessionHandler'))

            media_chan = make_channel_proxy(conn, mc.path,
                'Channel.Interface.Group')
            media_iface = make_channel_proxy(conn, mc.path,
                'Channel.Type.StreamedMedia')
    else:
        call_async(q, conn.Requests, 'CreateChannel',
                { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA,
                  cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
                  cs.TARGET_HANDLE: remote_handle,
                  })
        ret, old_sig, new_sig = q.expect_many(
            EventPattern('dbus-return', method='CreateChannel'),
            EventPattern('dbus-signal', signal='NewChannel',
                predicate=lambda e:
                cs.CHANNEL_TYPE_CONTACT_LIST not in e.args),
            EventPattern('dbus-signal', signal='NewChannels',
                predicate=lambda e:
                    cs.CHANNEL_TYPE_CONTACT_LIST not in
                    e.args[0][0][1].values()),
            )
        path = ret.value[0]
        media_chan = make_channel_proxy(conn, path, 'Channel.Interface.Group')
        media_iface = make_channel_proxy(conn, path,
                'Channel.Type.StreamedMedia')
        call_async(q, media_iface, 'RequestStreams',
                remote_handle, [cs.MEDIA_STREAM_TYPE_AUDIO])
        e = q.expect('dbus-signal', signal='NewSessionHandler')

    req1 = q.expect('http-request', method='GET', path='/create_session')
    req2 = q.expect('http-request', method='GET', path='/create_session')

    if too_slow is not None:
        test_too_slow(q, bus, conn, stream, req1, req2, media_chan, too_slow)
        return

    if incoming:
        assertLength(0, media_iface.ListStreams())
        # Accept the call.
        media_chan.AddMembers([self_handle], '')

    # In response to the streams call, we now have two HTTP requests
    # (for RTP and RTCP)
    handle_request(req1.request, 0)
    handle_request(req2.request, 1)

    if incoming:
        # We accepted the call, and it should get a new, bidirectional stream
        # now that the relay info request has finished. This tests against a
        # regression of bug #24023.
        q.expect('dbus-signal', signal='StreamAdded',
            args=[1, remote_handle, cs.MEDIA_STREAM_TYPE_AUDIO])
        q.expect('dbus-signal', signal='StreamDirectionChanged',
            args=[1, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0])
    else:
        # Now that we have the relay info, RequestStreams can return
        q.expect('dbus-return', method='RequestStreams')

    session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler')
    session_handler.Ready()

    e = q.expect('dbus-signal', signal='NewStreamHandler')
    stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler')

    # Exercise channel properties
    channel_props = media_chan.GetAll(
        cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE)
    assert channel_props['TargetHandle'] == remote_handle
    assert channel_props['TargetHandleType'] == cs.HT_CONTACT
    assert channel_props['TargetID'] == '*****@*****.**'
    assert channel_props['Requested'] == (not incoming)

    # The new API for STUN servers etc.
    sh_props = stream_handler.GetAll(
        cs.STREAM_HANDLER, dbus_interface=dbus.PROPERTIES_IFACE)

    assert sh_props['NATTraversal'] == 'gtalk-p2p'
    assert sh_props['CreatedLocally'] == (not incoming)

    # If Gabble has erroneously paid attention to the contact [email protected] who
    # sent us a google:jingleinfo stanza, this assertion will fail.
    assertEquals([(expected_stun_server, expected_stun_port)],
        sh_props['STUNServers'])

    credentials_used = {}
    credentials = {}

    for relay in sh_props['RelayInfo']:
        assert relay['ip'] == '127.0.0.1', sh_props['RelayInfo']
        assert relay['type'] in ('udp', 'tcp', 'tls')
        assert relay['component'] in (1, 2)

        if relay['type'] == 'udp':
            assert relay['port'] == 11111, sh_props['RelayInfo']
        elif relay['type'] == 'tcp':
            assert relay['port'] == 22222, sh_props['RelayInfo']
        elif relay['type'] == 'tls':
            assert relay['port'] == 443, sh_props['RelayInfo']

        assert relay['username'][:8] == 'UUUUUUUU', sh_props['RelayInfo']
        assert relay['password'][:8] == 'PPPPPPPP', sh_props['RelayInfo']
        assert relay['password'][8:] == relay['username'][8:], \
                sh_props['RelayInfo']
        assert (relay['password'][8:], relay['type']) not in credentials_used
        credentials_used[(relay['password'][8:], relay['type'])] = 1
        credentials[(relay['component'], relay['type'])] = relay['password'][8:]

    assert (1, 'udp') in credentials
    assert (1, 'tcp') in credentials
    assert (1, 'tls') in credentials
    assert (2, 'udp') in credentials
    assert (2, 'tcp') in credentials
    assert (2, 'tls') in credentials

    assert ('0', 'udp') in credentials_used
    assert ('0', 'tcp') in credentials_used
    assert ('0', 'tls') in credentials_used
    assert ('1', 'udp') in credentials_used
    assert ('1', 'tcp') in credentials_used
    assert ('1', 'tls') in credentials_used

    # consistency check, since we currently reimplement Get separately
    for k in sh_props:
        assert sh_props[k] == stream_handler.Get(
                'org.freedesktop.Telepathy.Media.StreamHandler', k,
                dbus_interface=dbus.PROPERTIES_IFACE), k

    media_chan.RemoveMembers([self_handle], '')

    if incoming:
        q.expect_many(
            EventPattern('stream-iq',
                predicate=lambda e: e.query is not None and
                    e.query.name == 'jingle' and
                    e.query['action'] == 'session-terminate'),
            EventPattern('dbus-signal', signal='Closed'),
            )
    else:
        # We haven't sent a session-initiate, so we shouldn't expect to send a
        # session-terminate.
        q.expect('dbus-signal', signal='Closed')
def test(q, bus, conn, stream):
    conn.Connect()

    _, iq_event, disco_event = q.expect_many(
        EventPattern('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]),
        EventPattern('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard'),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, iq_event.stanza)
    announce_gadget(q, stream, disco_event.stanza)

    act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties')
    buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
    simple_presence_iface = dbus.Interface(conn, 'org.freedesktop.Telepathy.Connection.Interface.SimplePresence')

    q.expect('dbus-signal', signal='GadgetDiscovered')
    gadget_publish(q, stream, conn, True)

    # join a room
    room_handle, room_path = join_channel('*****@*****.**',
            q, conn, stream)

    call_async (q, buddy_info_iface, 'SetActivities', [("roomid", room_handle)])

    # pubsub activity iq
    event = q.expect('stream-iq', iq_type='set', query_name='pubsub',
        query_ns=ns.PUBSUB)
    acknowledge_iq(stream, event.stanza)

    event = q.expect('dbus-return', method='SetActivities')

    # make activity public
    call_async(q, act_prop_iface, 'SetProperties',
            1, {'title': 'My test activity', 'private': False})

    # pseudo invite
    event = q.expect('stream-message', to='gadget.localhost')
    message = event.stanza
    properties = xpath.queryForNodes('/message/properties', message)
    assert (properties is not None and len(properties) == 1), repr(properties)
    assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS
    assert properties[0]['room'] == '*****@*****.**'
    assert properties[0]['activity'] == 'roomid'

    # invite
    event = q.expect('stream-message', to='*****@*****.**')
    message = event.stanza
    x = xpath.queryForNodes('/message/x', message)
    assert (x is not None and len(x) == 1), repr(x)
    assert x[0].uri == ns.MUC_USER

    invites = xpath.queryForNodes('/x/invite', x[0])
    assert (invites is not None and len(invites) == 1), repr(invites)
    assert invites[0]['to'] == 'gadget.localhost'

    # pubsub activity prop iq
    event = q.expect('stream-iq')
    acknowledge_iq(stream, event.stanza)

    # pubsub activity iq
    event = q.expect('stream-iq')
    acknowledge_iq(stream, event.stanza)

    event = q.expect('dbus-return', method='SetProperties')

    # Gadget joins the room
    stream.send(make_muc_presence('none', 'participant', '*****@*****.**',
        'inspector', 'gadget.localhost'))

    muc = bus.get_object(conn.bus_name, room_path)
    muc_group = dbus.Interface(muc, "org.freedesktop.Telepathy.Channel.Interface.Group")

    sync_stream(q, stream)
    members = muc_group.GetMembers()
    assert conn.InspectHandles(1, members) == ['[email protected]/test']

    # Regression test for a nasty bug caused by the presence cache handling
    # the inspector presence as a non-MUC one because the inspector is not
    # added to MUC's members.
    handle = conn.RequestHandles(1, ['*****@*****.**'])[0]
    presence = simple_presence_iface.GetPresences([handle])
    assert presence[handle] == (7, 'unknown', '')

    # PEP activity update
    disconnect_conn(q, conn, stream, [EventPattern('stream-iq')])[0]
    conn2.Connect()
    q.expect('dbus-signal',
             signal='StatusChanged',
             args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])
    q.expect('stream-authenticated')
    q.expect('dbus-signal',
             signal='PresencesChanged',
             args=[{
                 1L: (cs.PRESENCE_AVAILABLE, 'available', '')
             }])
    q.expect('dbus-signal',
             signal='StatusChanged',
             args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    # Disconnection 2
    disconnect_conn(q, conn2, stream2)


if __name__ == '__main__':
    queue = servicetest.IteratingEventQueue(None)
    queue.verbose = (os.environ.get('CHECK_TWISTED_VERBOSE', '') != ''
                     or '-v' in sys.argv)

    bus = dbus.SessionBus()

    params = {
        'account': 'test1@localhost/Resource',
        'password': '******',
        'resource': 'Resource',
        'server': 'localhost',
        'port': dbus.UInt32(4242),
Beispiel #26
0
                 query_ns=ns.PUBSUB,
                 to='*****@*****.**')
    send_error_reply(stream, e.stanza,
                     elem('error', type='auth')(elem(ns.STANZA, 'forbidden')))
    e = q.expect('dbus-error', method='RequestLocation')
    assertEquals(cs.PERMISSION_DENIED, e.name)

    # FIXME: maybe we should check that the cache gets invalidated in this
    # case? We should also test whether or not the cache is invalidated
    # properly if the contact clears their PEP node.

    # Let's ask a final time, and disconnect while we're doing so, to make sure
    # this doesn't break Gabble or Wocky.
    call_async(q, conn.Location, 'RequestLocation', bob_handle)
    e = q.expect('stream-iq',
                 iq_type='get',
                 query_ns=ns.PUBSUB,
                 to='*****@*****.**')
    # Tasty argument unpacking. disconnect_conn returns two lists, one for
    # expeced_before=[] and one for expected_after=[...]
    _, (e, ) = disconnect_conn(
        q,
        conn,
        stream,
        expected_after=[EventPattern('dbus-error', method='RequestLocation')])
    assertEquals(cs.CANCELLED, e.name)


if __name__ == '__main__':
    exec_test(test, do_connect=False)
Beispiel #27
0
    assertEquals(location['country'], 'Chad')

    # Let's ask again; this time Bob's server hates us for some reason.
    call_async(q, conn.Location, 'RequestLocation', bob_handle)
    e = q.expect('stream-iq', iq_type='get', query_ns=ns.PUBSUB,
        to='*****@*****.**')
    send_error_reply(stream, e.stanza,
        elem('error', type='auth')(
          elem(ns.STANZA, 'forbidden')
        ))
    e = q.expect('dbus-error', method='RequestLocation')
    assertEquals(cs.PERMISSION_DENIED, e.name)

    # FIXME: maybe we should check that the cache gets invalidated in this
    # case? We should also test whether or not the cache is invalidated
    # properly if the contact clears their PEP node.

    # Let's ask a final time, and disconnect while we're doing so, to make sure
    # this doesn't break Gabble or Wocky.
    call_async(q, conn.Location, 'RequestLocation', bob_handle)
    e = q.expect('stream-iq', iq_type='get', query_ns=ns.PUBSUB,
        to='*****@*****.**')
    # Tasty argument unpacking. disconnect_conn returns two lists, one for
    # expeced_before=[] and one for expected_after=[...]
    _, (e, ) = disconnect_conn(q, conn, stream,
        expected_after=[EventPattern('dbus-error', method='RequestLocation')])
    assertEquals(cs.CANCELLED, e.name)

if __name__ == '__main__':
    exec_test(test, do_connect=False)
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control,
         access_control_param):
    if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]:
        # disable SOCKS5 relay tests because proxy can't be used with muc
        # contacts atm
        return

    if access_control == cs.SOCKET_ACCESS_CONTROL_CREDENTIALS:
        print("Skip Socket_Access_Control_Credentials (fdo #45445)")
        return

    iq_event, disco_event = q.expect_many(
        EventPattern('stream-iq',
                     to=None,
                     query_ns='vcard-temp',
                     query_name='vCard'),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, iq_event.stanza)

    announce_socks5_proxy(q, stream, disco_event.stanza)

    # join the muc
    call_async(
        q, conn.Requests, 'CreateChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.TARGET_ID: '*****@*****.**'
        })

    q.expect_many(
        EventPattern(
            'dbus-signal',
            signal='MembersChangedDetailed',
            predicate=lambda e: e.args[0] == [] and  # added
            e.args[1] == [] and  # removed
            e.args[2] == [] and  # local pending
            len(e.args[3]) == 1 and  # remote pending
            e.args[4].get('actor', 0) == 0 and e.args[4].get(
                'change-reason', 0) == 0 and e.args[4]['contact-ids'][e.args[
                    3][0]] == '[email protected]/test'),
        EventPattern('stream-presence', to='[email protected]/test'))

    # Send presence for other member of room.
    stream.send(
        make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob'))

    # Send presence for own membership of room.
    stream.send(
        make_muc_presence('none', 'participant', '*****@*****.**',
                          'test'))

    event = q.expect(
        'dbus-signal',
        signal='MembersChangedDetailed',
        predicate=lambda e: len(e.args[0]) == 2 and  # added
        e.args[1] == [] and  # removed
        e.args[2] == [] and  # local pending
        e.args[3] == [] and  # remote pending
        e.args[4].get('actor', 0) == 0 and e.args[4].get('change-reason', 0) ==
        0 and set([e.args[4]['contact-ids'][h] for h in e.args[0]]) == set(
            ['[email protected]/test', '[email protected]/bob']))

    for h in event.args[0]:
        if event.args[4]['contact-ids'][h] == '[email protected]/bob':
            bob_handle = h

    event = q.expect('dbus-return', method='CreateChannel')

    # Bob offers a stream tube
    stream_tube_id = 666
    presence = make_muc_presence('owner', 'moderator', '*****@*****.**',
                                 'bob')
    tubes = presence.addElement((ns.TUBES, 'tubes'))
    tube = tubes.addElement((None, 'tube'))
    tube['type'] = 'stream'
    tube['service'] = 'echo'
    tube['id'] = str(stream_tube_id)
    parameters = tube.addElement((None, 'parameters'))
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 's'
    parameter['type'] = 'str'
    parameter.addContent('hello')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'ay'
    parameter['type'] = 'bytes'
    parameter.addContent('aGVsbG8=')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'u'
    parameter['type'] = 'uint'
    parameter.addContent('123')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'i'
    parameter['type'] = 'int'
    parameter.addContent('-123')

    stream.send(presence)

    # text channel
    new_event = q.expect('dbus-signal', signal='NewChannels')

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT

    def new_chan_predicate(e):
        path, props = e.args[0][0]
        return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE

    # tube channel is announced
    new_event = q.expect('dbus-signal',
                         signal='NewChannels',
                         predicate=new_chan_predicate)

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
    assert props[cs.INITIATOR_HANDLE] == bob_handle
    assert props[cs.INITIATOR_ID] == '[email protected]/bob'
    assertSameSets([cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE],
                   props[cs.INTERFACES])
    assert props[cs.REQUESTED] == False
    assert props[cs.TARGET_ID] == '*****@*****.**'
    assert props[cs.STREAM_TUBE_SERVICE] == 'echo'
    assert props[cs.TUBE_PARAMETERS] == {
        's': 'hello',
        'ay': b'hello',
        'u': 123,
        'i': -123
    }
    assert access_control in \
            props[cs.STREAM_TUBE_SUPPORTED_SOCKET_TYPES][address_type]

    tube_chan = bus.get_object(conn.bus_name, path)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE,
                                  dbus_interface=cs.PROPERTIES_IFACE,
                                  byte_arrays=True)
    tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
    assert tube_props['Parameters'] == sample_parameters
    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING

    # Accept the tube
    call_async(q,
               tube_iface,
               'Accept',
               address_type,
               access_control,
               access_control_param,
               byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='Accept'),
        EventPattern('dbus-signal', signal='TubeChannelStateChanged',
                     args=[2]))

    address = accept_return_event.value[0]
    if isinstance(address, bytes):
        address = address.decode()

    socket_event, si_event, conn_id = t.connect_to_cm_socket(
        q, '[email protected]/bob', address_type, address, access_control,
        access_control_param)

    protocol = socket_event.protocol
    protocol.sendData(b"hello initiator")

    def accept_tube_si_connection():
        bytestream, profile = create_from_si_offer(stream, q, bytestream_cls,
                                                   si_event.stanza,
                                                   '[email protected]/test')

        assert profile == ns.TUBES

        muc_stream_node = xpath.queryForNodes(
            '/iq/si/muc-stream[@xmlns="%s"]' % ns.TUBES, si_event.stanza)[0]
        assert muc_stream_node is not None
        assert muc_stream_node['tube'] == str(stream_tube_id)

        # set the real jid of the target as 'to' because the XMPP server changes
        # it when delivering the IQ
        result, si = bytestream.create_si_reply(si_event.stanza,
                                                'test@localhost/Resource')
        si.addElement((ns.TUBES, 'tube'))
        stream.send(result)

        bytestream.wait_bytestream_open()
        return bytestream

    bytestream = accept_tube_si_connection()

    binary = bytestream.get_data()
    assert binary == b'hello initiator'

    # reply on the socket
    bytestream.send_data(b'hi joiner!')

    q.expect('socket-data', protocol=protocol, data=b"hi joiner!")

    # peer closes the bytestream
    bytestream.close()
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_LOST, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(
        q, '[email protected]/bob', address_type, address, access_control,
        access_control_param)

    # bytestream is refused
    send_error_reply(stream, si_event.stanza)
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_REFUSED, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(
        q, '[email protected]/bob', address_type, address, access_control,
        access_control_param)

    protocol = socket_event.protocol
    bytestream = accept_tube_si_connection()

    # disconnect local socket
    protocol.transport.loseConnection()
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CANCELLED, e.args[1])

    # OK, we're done
    disconnect_conn(q, conn, stream)
def test(q, bus, conn, stream):
    # Initial vCard request. Respond only after we call SetAliases().
    vcard_get_event = q.expect('stream-iq', iq_type='get', to=None,
        query_ns=ns.VCARD_TEMP, query_name='vCard')
    sync_stream(q, stream)

    handle = conn.Properties.Get(cs.CONN, "SelfHandle")
    call_async(q, conn.Aliasing, 'SetAliases', {handle: 'Robert the Bruce'})
    sync_dbus(bus, q, conn)
    acknowledge_iq(stream, vcard_get_event.stanza)

    # Gabble sets a new vCard with our nickname.
    vcard_set_event = q.expect('stream-iq', iq_type='set',
        query_ns=ns.VCARD_TEMP, query_name='vCard')
    assertEquals('Robert the Bruce', xpath.queryForString('/iq/vCard/NICKNAME',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/PHOTO',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/FN',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/N',
        vcard_set_event.stanza))

    # Before the server replies, the user sets their avatar
    call_async(q, conn.Avatars, 'SetAvatar', 'hello', 'image/png')
    sync_dbus(bus, q, conn)
    # This acknowledgement is for the nickname
    acknowledge_iq(stream, vcard_set_event.stanza)

    hello_binval = base64.b64encode('hello')

    # This sets the avatar
    vcard_set_event = q.expect('stream-iq', iq_type='set',
        query_ns=ns.VCARD_TEMP, query_name='vCard')
    assertEquals('Robert the Bruce', xpath.queryForString('/iq/vCard/NICKNAME',
        vcard_set_event.stanza))
    assertLength(1, xpath.queryForNodes('/iq/vCard/PHOTO',
        vcard_set_event.stanza))
    assertEquals('image/png', xpath.queryForString('/iq/vCard/PHOTO/TYPE',
        vcard_set_event.stanza))
    binval = xpath.queryForString('/iq/vCard/PHOTO/BINVAL',
        vcard_set_event.stanza)
    assertEquals(hello_binval, binval.strip())
    assertEquals(None, xpath.queryForNodes('/iq/vCard/FN',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/N',
        vcard_set_event.stanza))

    # Before the server replies, the user sets their ContactInfo
    call_async(q, conn.ContactInfo, 'SetContactInfo',
               [(u'fn', [], [u'King Robert I']),
                (u'n', [], [u'de Brus', u'Robert', u'', u'King', u'']),
                (u'nickname', [], [u'Bob'])])
    sync_dbus(bus, q, conn)
    # This acknowledgement is for the avatar; SetAvatar won't happen
    # until this has
    acknowledge_iq(stream, vcard_set_event.stanza)

    # This sets the ContactInfo
    vcard_set_event, _ = q.expect_many(
        EventPattern('stream-iq', iq_type='set',
                     query_ns=ns.VCARD_TEMP, query_name='vCard'),
        EventPattern('dbus-return', method='SetAvatar'))

    assertEquals('Bob', xpath.queryForString('/iq/vCard/NICKNAME',
        vcard_set_event.stanza))
    assertLength(1, xpath.queryForNodes('/iq/vCard/PHOTO',
        vcard_set_event.stanza))
    assertEquals('image/png', xpath.queryForString('/iq/vCard/PHOTO/TYPE',
        vcard_set_event.stanza))
    binval = xpath.queryForString('/iq/vCard/PHOTO/BINVAL',
        vcard_set_event.stanza)
    assertEquals(hello_binval, binval.strip())
    assertLength(1, xpath.queryForNodes('/iq/vCard/N',
        vcard_set_event.stanza))
    assertEquals('Robert', xpath.queryForString('/iq/vCard/N/GIVEN',
        vcard_set_event.stanza))
    assertEquals('de Brus', xpath.queryForString('/iq/vCard/N/FAMILY',
        vcard_set_event.stanza))
    assertEquals('King', xpath.queryForString('/iq/vCard/N/PREFIX',
        vcard_set_event.stanza))
    assertEquals('King Robert I', xpath.queryForString('/iq/vCard/FN',
        vcard_set_event.stanza))

    # Before the server replies, the user unsets their avatar
    call_async(q, conn.Avatars, 'SetAvatar', '', '')
    sync_dbus(bus, q, conn)

    # This acknowledgement is for the ContactInfo; SetContactInfo won't happen
    # until this has
    acknowledge_iq(stream, vcard_set_event.stanza)

    vcard_set_event, _ = q.expect_many(
        EventPattern('stream-iq', iq_type='set',
                     query_ns=ns.VCARD_TEMP, query_name='vCard'),
        EventPattern('dbus-return', method='SetContactInfo'))
    assertEquals('Bob', xpath.queryForString('/iq/vCard/NICKNAME',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/PHOTO',
        vcard_set_event.stanza))
    assertLength(1, xpath.queryForNodes('/iq/vCard/N',
        vcard_set_event.stanza))
    assertEquals('Robert', xpath.queryForString('/iq/vCard/N/GIVEN',
        vcard_set_event.stanza))
    assertEquals('de Brus', xpath.queryForString('/iq/vCard/N/FAMILY',
        vcard_set_event.stanza))
    assertEquals('King', xpath.queryForString('/iq/vCard/N/PREFIX',
        vcard_set_event.stanza))
    assertEquals('King Robert I', xpath.queryForString('/iq/vCard/FN',
        vcard_set_event.stanza))

    # This acknowledgement is for the avatar; SetAvatar won't finish
    # until this is received
    acknowledge_iq(stream, vcard_set_event.stanza)
    q.expect('dbus-return', method='SetAvatar')

    # Now Gabble gets disconnected.
    sync_stream(q, stream)
    disconnect_conn(q, conn, stream)
def test(q, bus, conn, stream, bytestream_cls,
        address_type, access_control, access_control_param):
    if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]:
        # disable SOCKS5 relay tests because proxy can't be used with muc
        # contacts atm
        return

    iq_event, disco_event = q.expect_many(
        EventPattern('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard'),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, iq_event.stanza)

    announce_socks5_proxy(q, stream, disco_event.stanza)

    call_async(q, conn, 'RequestHandles', 2,
        ['*****@*****.**'])

    event = q.expect('dbus-return', method='RequestHandles')
    handles = event.value[0]
    room_handle = handles[0]

    # join the muc
    call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM,
        room_handle, True)

    _, stream_event = q.expect_many(
        EventPattern('dbus-signal', signal='MembersChanged',
            args=[u'', [], [], [], [2], 0, 0]),
        EventPattern('stream-presence', to='[email protected]/test'))

    # Send presence for other member of room.
    stream.send(make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob'))

    # Send presence for own membership of room.
    stream.send(make_muc_presence('none', 'participant', '*****@*****.**', 'test'))

    q.expect('dbus-signal', signal='MembersChanged',
            args=[u'', [2, 3], [], [], [], 0, 0])

    assert conn.InspectHandles(1, [2]) == ['[email protected]/test']
    assert conn.InspectHandles(1, [3]) == ['[email protected]/bob']
    bob_handle = 3

    event = q.expect('dbus-return', method='RequestChannel')

    # Bob offers a stream tube
    stream_tube_id = 666
    presence = make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob')
    tubes = presence.addElement((ns.TUBES, 'tubes'))
    tube = tubes.addElement((None, 'tube'))
    tube['type'] = 'stream'
    tube['service'] = 'echo'
    tube['id'] = str(stream_tube_id)
    parameters = tube.addElement((None, 'parameters'))
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 's'
    parameter['type'] = 'str'
    parameter.addContent('hello')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'ay'
    parameter['type'] = 'bytes'
    parameter.addContent('aGVsbG8=')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'u'
    parameter['type'] = 'uint'
    parameter.addContent('123')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'i'
    parameter['type'] = 'int'
    parameter.addContent('-123')

    stream.send(presence)

    # text channel
    event, new_event = q.expect_many(
        EventPattern('dbus-signal', signal='NewChannel'),
        EventPattern('dbus-signal', signal='NewChannels'))

    assert event.args[1] == cs.CHANNEL_TYPE_TEXT, event.args

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT

    # tubes channel is automatically created
    event, new_event = q.expect_many(
        EventPattern('dbus-signal', signal='NewChannel'),
        EventPattern('dbus-signal', signal='NewChannels'))

    assert event.args[1] == cs.CHANNEL_TYPE_TUBES, event.args
    assert event.args[2] == cs.HT_ROOM
    assert event.args[3] == room_handle

    tubes_chan = bus.get_object(conn.bus_name, event.args[0])
    tubes_iface = dbus.Interface(tubes_chan, event.args[1])

    channel_props = tubes_chan.GetAll(cs.CHANNEL, dbus_interface=cs.PROPERTIES_IFACE)
    assert channel_props['TargetID'] == '*****@*****.**', channel_props
    assert channel_props['Requested'] == False
    assert channel_props['InitiatorID'] == ''
    assert channel_props['InitiatorHandle'] == 0

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES

    tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP)

    q.expect('dbus-signal', signal='NewTube',
        args=[stream_tube_id, bob_handle, 1, 'echo', sample_parameters, 0])

    expected_tube = (stream_tube_id, bob_handle, cs.TUBE_TYPE_STREAM, 'echo',
        sample_parameters, cs.TUBE_STATE_LOCAL_PENDING)
    tubes = tubes_iface.ListTubes(byte_arrays=True)
    assert tubes == [(
        stream_tube_id,
        bob_handle,
        1,      # Stream
        'echo',
        sample_parameters,
        cs.TUBE_CHANNEL_STATE_LOCAL_PENDING
        )]

    assert len(tubes) == 1, unwrap(tubes)
    t.check_tube_in_tubes(expected_tube, tubes)

    # tube channel is also announced (new API)
    new_event = q.expect('dbus-signal', signal='NewChannels')

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
    assert props[cs.INITIATOR_HANDLE] == bob_handle
    assert props[cs.INITIATOR_ID] == '[email protected]/bob'
    assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE]
    assert props[cs.REQUESTED] == False
    assert props[cs.TARGET_HANDLE] == room_handle
    assert props[cs.TARGET_ID] == '*****@*****.**'
    assert props[cs.STREAM_TUBE_SERVICE] == 'echo'
    assert props[cs.TUBE_PARAMETERS] == {'s': 'hello', 'ay': 'hello', 'u': 123, 'i': -123}
    assert access_control in \
            props[cs.STREAM_TUBE_SUPPORTED_SOCKET_TYPES][address_type]

    tube_chan = bus.get_object(conn.bus_name, path)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE,
        byte_arrays=True)
    assert tube_props['Parameters'] == sample_parameters
    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING

    # Accept the tube
    call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id,
        address_type, access_control, access_control_param, byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='AcceptStreamTube'),
        EventPattern('dbus-signal', signal='TubeStateChanged',
            args=[stream_tube_id, 2]))

    address = accept_return_event.value[0]

    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    protocol = socket_event.protocol
    protocol.sendData("hello initiator")

    def accept_tube_si_connection():
        bytestream, profile = create_from_si_offer(stream, q, bytestream_cls, si_event.stanza,
                '[email protected]/test')

        assert profile == ns.TUBES

        muc_stream_node = xpath.queryForNodes('/iq/si/muc-stream[@xmlns="%s"]' %
            ns.TUBES, si_event.stanza)[0]
        assert muc_stream_node is not None
        assert muc_stream_node['tube'] == str(stream_tube_id)

        # set the real jid of the target as 'to' because the XMPP server changes
        # it when delivering the IQ
        result, si = bytestream.create_si_reply(si_event.stanza, 'test@localhost/Resource')
        si.addElement((ns.TUBES, 'tube'))
        stream.send(result)

        bytestream.wait_bytestream_open()
        return bytestream

    bytestream = accept_tube_si_connection()

    binary = bytestream.get_data()
    assert binary == 'hello initiator'

    # reply on the socket
    bytestream.send_data('hi joiner!')

    q.expect('socket-data', protocol=protocol, data="hi joiner!")

    # peer closes the bytestream
    bytestream.close()
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_LOST, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    # bytestream is refused
    send_error_reply(stream, si_event.stanza)
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_REFUSED, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    protocol = socket_event.protocol
    bytestream = accept_tube_si_connection()

    # disconnect local socket
    protocol.transport.loseConnection()
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CANCELLED, e.args[1])

    # OK, we're done
    disconnect_conn(q, conn, stream,
        [EventPattern('dbus-signal', signal='TubeClosed', args=[stream_tube_id])])
def test(q, bus, conn, stream):
    # Initial vCard request. Respond only after we call SetAliases().
    vcard_get_event = q.expect('stream-iq', iq_type='get', to=None,
        query_ns=ns.VCARD_TEMP, query_name='vCard')
    sync_stream(q, stream)

    handle = conn.Properties.Get(cs.CONN, "SelfHandle")
    call_async(q, conn.Aliasing, 'SetAliases', {handle: 'Robert the Bruce'})
    sync_dbus(bus, q, conn)
    acknowledge_iq(stream, vcard_get_event.stanza)

    # Gabble sets a new vCard with our nickname.
    vcard_set_event = q.expect('stream-iq', iq_type='set',
        query_ns=ns.VCARD_TEMP, query_name='vCard')
    assertEquals('Robert the Bruce', xpath.queryForString('/iq/vCard/NICKNAME',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/PHOTO',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/FN',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/N',
        vcard_set_event.stanza))

    # Before the server replies, the user sets their avatar
    call_async(q, conn.Avatars, 'SetAvatar', b'hello', 'image/png')
    sync_dbus(bus, q, conn)
    # This acknowledgement is for the nickname
    acknowledge_iq(stream, vcard_set_event.stanza)

    hello_binval = base64.b64encode(b'hello').decode()

    # This sets the avatar
    vcard_set_event = q.expect('stream-iq', iq_type='set',
        query_ns=ns.VCARD_TEMP, query_name='vCard')
    assertEquals('Robert the Bruce', xpath.queryForString('/iq/vCard/NICKNAME',
        vcard_set_event.stanza))
    assertLength(1, xpath.queryForNodes('/iq/vCard/PHOTO',
        vcard_set_event.stanza))
    assertEquals('image/png', xpath.queryForString('/iq/vCard/PHOTO/TYPE',
        vcard_set_event.stanza))
    binval = xpath.queryForString('/iq/vCard/PHOTO/BINVAL',
        vcard_set_event.stanza)
    assertEquals(hello_binval, binval.strip())
    assertEquals(None, xpath.queryForNodes('/iq/vCard/FN',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/N',
        vcard_set_event.stanza))

    # Before the server replies, the user sets their ContactInfo
    call_async(q, conn.ContactInfo, 'SetContactInfo',
               [(u'fn', [], [u'King Robert I']),
                (u'n', [], [u'de Brus', u'Robert', u'', u'King', u'']),
                (u'nickname', [], [u'Bob'])])
    sync_dbus(bus, q, conn)
    # This acknowledgement is for the avatar; SetAvatar won't happen
    # until this has
    acknowledge_iq(stream, vcard_set_event.stanza)

    # This sets the ContactInfo
    vcard_set_event, _ = q.expect_many(
        EventPattern('stream-iq', iq_type='set',
                     query_ns=ns.VCARD_TEMP, query_name='vCard'),
        EventPattern('dbus-return', method='SetAvatar'))

    assertEquals('Bob', xpath.queryForString('/iq/vCard/NICKNAME',
        vcard_set_event.stanza))
    assertLength(1, xpath.queryForNodes('/iq/vCard/PHOTO',
        vcard_set_event.stanza))
    assertEquals('image/png', xpath.queryForString('/iq/vCard/PHOTO/TYPE',
        vcard_set_event.stanza))
    binval = xpath.queryForString('/iq/vCard/PHOTO/BINVAL',
        vcard_set_event.stanza)
    assertEquals(hello_binval, binval.strip())
    assertLength(1, xpath.queryForNodes('/iq/vCard/N',
        vcard_set_event.stanza))
    assertEquals('Robert', xpath.queryForString('/iq/vCard/N/GIVEN',
        vcard_set_event.stanza))
    assertEquals('de Brus', xpath.queryForString('/iq/vCard/N/FAMILY',
        vcard_set_event.stanza))
    assertEquals('King', xpath.queryForString('/iq/vCard/N/PREFIX',
        vcard_set_event.stanza))
    assertEquals('King Robert I', xpath.queryForString('/iq/vCard/FN',
        vcard_set_event.stanza))

    # Before the server replies, the user unsets their avatar
    call_async(q, conn.Avatars, 'SetAvatar', '', '')
    sync_dbus(bus, q, conn)

    # This acknowledgement is for the ContactInfo; SetContactInfo won't happen
    # until this has
    acknowledge_iq(stream, vcard_set_event.stanza)

    vcard_set_event, _ = q.expect_many(
        EventPattern('stream-iq', iq_type='set',
                     query_ns=ns.VCARD_TEMP, query_name='vCard'),
        EventPattern('dbus-return', method='SetContactInfo'))
    assertEquals('Bob', xpath.queryForString('/iq/vCard/NICKNAME',
        vcard_set_event.stanza))
    assertEquals(None, xpath.queryForNodes('/iq/vCard/PHOTO',
        vcard_set_event.stanza))
    assertLength(1, xpath.queryForNodes('/iq/vCard/N',
        vcard_set_event.stanza))
    assertEquals('Robert', xpath.queryForString('/iq/vCard/N/GIVEN',
        vcard_set_event.stanza))
    assertEquals('de Brus', xpath.queryForString('/iq/vCard/N/FAMILY',
        vcard_set_event.stanza))
    assertEquals('King', xpath.queryForString('/iq/vCard/N/PREFIX',
        vcard_set_event.stanza))
    assertEquals('King Robert I', xpath.queryForString('/iq/vCard/FN',
        vcard_set_event.stanza))

    # This acknowledgement is for the avatar; SetAvatar won't finish
    # until this is received
    acknowledge_iq(stream, vcard_set_event.stanza)
    q.expect('dbus-return', method='SetAvatar')

    # Now Gabble gets disconnected.
    sync_stream(q, stream)
    disconnect_conn(q, conn, stream)
    # Connection 1 blocks because the fake jabber server behind conn1 does not
    # proceed to the tls handshake. The second connection is independant and
    # should work.

    # Connection 2
    conn2.Connect()
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])
    q.expect('stream-authenticated')
    q.expect('dbus-signal', signal='PresencesChanged',
        args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}])
    q.expect('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    # Disconnection 2
    disconnect_conn(q, conn2, stream2)

if __name__ == '__main__':
    queue = servicetest.IteratingEventQueue(None)
    queue.verbose = (
        os.environ.get('CHECK_TWISTED_VERBOSE', '') != ''
        or '-v' in sys.argv)

    bus = dbus.SessionBus()

    params = {
        'account': 'test1@localhost/Resource',
        'password': '******',
        'resource': 'Resource',
        'server': 'localhost',
        'port': dbus.UInt32(4242),
Beispiel #33
0
def test(q, bus, conn, stream):
    event = q.expect('stream-iq', to='localhost',
                query_ns='http://jabber.org/protocol/disco#items')

    result = make_result_iq(stream, event.stanza)
    item = result.firstChildElement().addElement('item')
    item['jid'] = 'conf.localhost'
    stream.send(result)

    event = q.expect('stream-iq', to='conf.localhost',
        query_ns='http://jabber.org/protocol/disco#info')
    result = make_result_iq(stream, event.stanza)
    feature = result.firstChildElement().addElement('feature')
    feature['var'] = 'http://jabber.org/protocol/muc'
    identity = result.firstChildElement().addElement('identity')
    identity['category'] = 'conference'
    identity['name'] = 'conference service'
    identity['type'] = 'text'
    stream.send(result)

    # Make sure the stream has been processed
    sync_stream(q, stream)

    properties = conn.Properties.GetAll(cs.CONN_IFACE_REQUESTS)
    assert properties.get('Channels') == [], properties['Channels']
    assert ({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_ROOM_LIST,
              cs.TARGET_HANDLE_TYPE: cs.HT_NONE,
             },
             [cs.CHANNEL_TYPE_ROOM_LIST + '.Server'],
             ) in properties.get('RequestableChannelClasses'),\
                     properties['RequestableChannelClasses']

    # FIXME: actually list the rooms!

    call_async(q, conn.Requests, 'CreateChannel',
            { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_ROOM_LIST,
              cs.TARGET_HANDLE_TYPE: cs.HT_NONE,
              cs.CHANNEL_TYPE_ROOM_LIST + '.Server':
                'conference.example.net',
              })

    ret, sig = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
        )
    path2 = ret.value[0]
    chan = bus.get_object(conn.bus_name, path2)

    props = ret.value[1]
    assertEquals(cs.CHANNEL_TYPE_ROOM_LIST, props[cs.CHANNEL_TYPE])
    assertEquals(cs.HT_NONE, props[cs.TARGET_HANDLE_TYPE])
    assertEquals(0, props[cs.TARGET_HANDLE])
    assertEquals('', props[cs.TARGET_ID])
    assertEquals(True, props[cs.REQUESTED])
    assertEquals(conn.Properties.Get(cs.CONN, "SelfHandle"), props[cs.INITIATOR_HANDLE])
    assertEquals('test@localhost', props[cs.INITIATOR_ID])
    assertEquals('conference.example.net', props[cs.CHANNEL_TYPE_ROOM_LIST+ '.Server'])

    assert sig.args[0][0][0] == path2
    assert sig.args[0][0][1] == props

    assert chan.Get(cs.CHANNEL_TYPE_ROOM_LIST, 'Server',
            dbus_interface=dbus.PROPERTIES_IFACE) == \
                    'conference.example.net'

    # FIXME: actually list the rooms!

    call_async(q, conn.Requests, 'EnsureChannel',
            { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_ROOM_LIST,
              cs.TARGET_HANDLE_TYPE: cs.HT_NONE,
              cs.CHANNEL_TYPE_ROOM_LIST + '.Server': 'conference.example.net',
            })

    ret = q.expect('dbus-return', method='EnsureChannel')
    yours, ensured_path, ensured_props = ret.value

    assert not yours
    assert ensured_path == path2, (ensured_path, path2)

    disconnect_conn(q, conn, stream, [
    EventPattern('dbus-signal', signal='Closed', path=path2),
    EventPattern('dbus-signal', signal='ChannelClosed', args=[path2])])