예제 #1
0
def test(q, bus, conn, stream):
    iq_event = q.expect('stream-iq',
                        to=None,
                        query_ns='vcard-temp',
                        query_name='vCard')

    acknowledge_iq(stream, iq_event.stanza)
    t.check_conn_properties(q, conn)

    # Create new style tube channel and make sure that is indeed
    # returned.
    muc = '*****@*****.**'

    call_async(
        q, conn.Requests, 'CreateChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.TARGET_ID: muc,
            cs.DBUS_TUBE_SERVICE_NAME: 'com.example.LolDongs'
        })

    q.expect('stream-presence', to='%s/test' % muc)
    stream.send(make_muc_presence('owner', 'moderator', muc, 'bob'))
    stream.send(make_muc_presence('none', 'participant', muc, 'test'))

    ret, _ = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
    )

    _, props = ret.value

    assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_DBUS_TUBE)
    assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM)
    assertEquals(props[cs.TARGET_ID], muc)

    # Now try joining the text muc before asking for the tube channel.
    muc = '*****@*****.**'

    join_muc(q, bus, conn, stream, muc)

    call_async(
        q, conn.Requests, 'CreateChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.TARGET_ID: muc,
            cs.DBUS_TUBE_SERVICE_NAME: 'com.example.LolDongs'
        })

    ret, _ = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
    )

    _, props = ret.value

    assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_DBUS_TUBE)
    assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM)
    assertEquals(props[cs.TARGET_ID], muc)
def test(q, bus, conn, stream, access_control):
    iq_event = q.expect('stream-iq',
                        to=None,
                        query_ns='vcard-temp',
                        query_name='vCard')

    acknowledge_iq(stream, iq_event.stanza)

    # check if we can request muc D-Bus tube
    t.check_conn_properties(q, conn)

    self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
    self_name = conn.inspect_contact_sync(self_handle)

    # offer a D-Bus tube to another room using new API
    muc = '*****@*****.**'
    request = {
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
        cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
        cs.TARGET_ID: '*****@*****.**',
        cs.DBUS_TUBE_SERVICE_NAME: 'com.example.TestCase',
    }
    join_muc(q, bus, conn, stream, muc, request=request)

    e = q.expect('dbus-signal', signal='NewChannels')

    channels = e.args[0]
    assert len(channels) == 1
    path, prop = channels[0]
    assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
    assert prop[cs.INITIATOR_ID] == '[email protected]/test'
    assert prop[cs.REQUESTED] == True
    assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
    assert prop[cs.TARGET_ID] == '*****@*****.**'
    assert prop[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
    assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [
        cs.SOCKET_ACCESS_CONTROL_CREDENTIALS,
        cs.SOCKET_ACCESS_CONTROL_LOCALHOST
    ]

    # check that the tube channel is in the channels list
    all_channels = conn.Get(cs.CONN_IFACE_REQUESTS,
                            'Channels',
                            dbus_interface=cs.PROPERTIES_IFACE,
                            byte_arrays=True)
    assertContains((path, prop), all_channels)

    tube_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'DBusTube')
    tube_props = tube_chan.Properties.GetAll(cs.CHANNEL_IFACE_TUBE,
                                             byte_arrays=True)

    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED

    # try to offer using a wrong access control
    try:
        tube_chan.DBusTube.Offer(sample_parameters,
                                 cs.SOCKET_ACCESS_CONTROL_PORT)
    except dbus.DBusException, e:
        assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
def test(q, bus, conn, stream):
    room = '*****@*****.**'

    chan, path, props, disco = join_muc(q,
                                        bus,
                                        conn,
                                        stream,
                                        room,
                                        also_capture=[
                                            EventPattern(
                                                'stream-iq',
                                                iq_type='get',
                                                query_name='query',
                                                query_ns=ns.DISCO_INFO,
                                                to=room)
                                        ])

    sync_dbus(bus, q, conn)

    # we call Close...
    call_async(q, chan, 'Close')
    q.expect('dbus-return', method='Close')

    # ...so gabble announces our unavailable presence to the MUC.
    event = q.expect('stream-presence', to=room + '/test')
    elem = event.stanza
    assertEquals('unavailable', elem['type'])

    # while we wait for the conference server to echo our unavailable
    # presence, we try and create the same channel again...
    call_async(
        q, conn.Requests, 'CreateChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.TARGET_ID: room
        })

    # ...which should fail because the channel hasn't closed yet.
    q.expect('dbus-error', method='CreateChannel', name=cs.NOT_AVAILABLE)

    # the conference server finally gets around to echoing our
    # unavailable presence...
    echo_muc_presence(q, stream, elem, 'none', 'participant')

    # ...and only now is the channel closed.
    q.expect_many(EventPattern('dbus-signal', signal='Closed'),
                  EventPattern('dbus-signal', signal='ChannelClosed'))

    # now that the channel has finally closed, let's try and request
    # it again which should succeed!
    chan, _, _ = join_muc(q, bus, conn, stream, room)

    # let's clear up though.
    chan.Close()
    event = q.expect('stream-presence', to=room + '/test')
    echo_muc_presence(q, stream, event.stanza, 'none', 'participant')
    q.expect_many(EventPattern('dbus-signal', signal='Closed'),
                  EventPattern('dbus-signal', signal='ChannelClosed'))
def test(q, bus, conn, stream, access_control):
    iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard')

    acknowledge_iq(stream, iq_event.stanza)

    # check if we can request muc D-Bus tube
    t.check_conn_properties(q, conn)

    self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
    self_name = conn.inspect_contact_sync(self_handle)

    # offer a D-Bus tube to another room using new API
    muc = '*****@*****.**'
    request = {
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
        cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
        cs.TARGET_ID: '*****@*****.**',
        cs.DBUS_TUBE_SERVICE_NAME: 'com.example.TestCase',
    }
    join_muc(q, bus, conn, stream, muc, request=request)

    e = q.expect('dbus-signal', signal='NewChannels')

    channels = e.args[0]
    assert len(channels) == 1
    path, prop = channels[0]
    assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
    assert prop[cs.INITIATOR_ID] == '[email protected]/test'
    assert prop[cs.REQUESTED] == True
    assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
    assert prop[cs.TARGET_ID] == '*****@*****.**'
    assert prop[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
    assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [cs.SOCKET_ACCESS_CONTROL_CREDENTIALS,
            cs.SOCKET_ACCESS_CONTROL_LOCALHOST]

    # check that the tube channel is in the channels list
    all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels',
        dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True)
    assertContains((path, prop), all_channels)

    tube_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'DBusTube')
    tube_props = tube_chan.Properties.GetAll(cs.CHANNEL_IFACE_TUBE, byte_arrays=True)

    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED

    # try to offer using a wrong access control
    try:
        tube_chan.DBusTube.Offer(sample_parameters, cs.SOCKET_ACCESS_CONTROL_PORT)
    except dbus.DBusException, e:
        assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
def test(q, bus, conn, stream):
    room = '*****@*****.**'

    chan, path, props, disco = join_muc(q, bus, conn, stream,
            room,
            also_capture=[EventPattern('stream-iq', iq_type='get',
                query_name='query', query_ns=ns.DISCO_INFO, to=room)])

    sync_dbus(bus, q, conn)

    # we call Close...
    call_async(q, chan, 'Close')
    q.expect('dbus-return', method='Close')

    # ...so gabble announces our unavailable presence to the MUC.
    event = q.expect('stream-presence', to=room + '/test')
    elem = event.stanza
    assertEquals('unavailable', elem['type'])

    # while we wait for the conference server to echo our unavailable
    # presence, we try and create the same channel again...
    call_async(q, conn.Requests, 'CreateChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.TARGET_ID: room
            })

    # ...which should fail because the channel hasn't closed yet.
    q.expect('dbus-error', method='CreateChannel', name=cs.NOT_AVAILABLE)

    # the conference server finally gets around to echoing our
    # unavailable presence...
    echo_muc_presence(q, stream, elem, 'none', 'participant')

    # ...and only now is the channel closed.
    q.expect_many(EventPattern('dbus-signal', signal='Closed'),
                  EventPattern('dbus-signal', signal='ChannelClosed'))

    # now that the channel has finally closed, let's try and request
    # it again which should succeed!
    chan, _, _ = join_muc(q, bus, conn, stream, room)

    # let's clear up though.
    chan.Close()
    event = q.expect('stream-presence', to=room + '/test')
    echo_muc_presence(q, stream, event.stanza, 'none', 'participant')
    q.expect_many(EventPattern('dbus-signal', signal='Closed'),
                  EventPattern('dbus-signal', signal='ChannelClosed'))
예제 #6
0
def test(q, bus, conn, stream):
    # The user happily joins a MUC
    chan, _, _ = join_muc(q, bus, conn, stream, MUC)
    muc_self_handle = chan.Properties.Get(cs.CHANNEL_IFACE_GROUP,
            "SelfHandle")
    muc_self_jid = conn.inspect_contact_sync(muc_self_handle)

    # But then Bob kicks us.
    bob_jid = '%s/bob' % MUC
    bob_handle = conn.get_contact_handle_sync(bob_jid)
    stream.send(
        elem('presence', from_=muc_self_jid, type='unavailable')(
          elem(ns.MUC_USER, 'x')(
            elem('item', affiliation='none', role='none')(
              elem('actor', jid=bob_jid),
              elem('reason')(
                u'bye'
              )
            ),
            elem('status', code='307'),
          )
        ))

    mcd_event = q.expect('dbus-signal', signal='MembersChangedDetailed')
    added, removed, local_pending, remote_pending, details = mcd_event.args
    assertEquals([], added)
    assertEquals([muc_self_handle], removed)
    assertEquals([], local_pending)
    assertEquals([], remote_pending)
    assertContains('actor', details)
    assertEquals(bob_handle, details['actor'])
    assertEquals(cs.GC_REASON_KICKED, details['change-reason'])
    assertEquals('bye', details['message'])

    q.expect('dbus-signal', signal='ChannelClosed')
예제 #7
0
def test(q, bus, conn, stream):
    # The user happily joins a MUC
    _, chan, _, _ = join_muc(q, bus, conn, stream, MUC)
    muc_self_handle = chan.Group.GetSelfHandle()
    muc_self_jid, = conn.InspectHandles(cs.HT_CONTACT, [muc_self_handle])

    # But then Bob kicks us.
    bob_jid = "%s/bob" % MUC
    bob_handle, = conn.RequestHandles(cs.HT_CONTACT, [bob_jid])
    stream.send(
        elem("presence", from_=muc_self_jid, type="unavailable")(
            elem(ns.MUC_USER, "x")(
                elem("item", affiliation="none", role="none")(elem("actor", jid=bob_jid), elem("reason")(u"bye")),
                elem("status", code="307"),
            )
        )
    )

    mcd_event = q.expect("dbus-signal", signal="MembersChangedDetailed")
    added, removed, local_pending, remote_pending, details = mcd_event.args
    assertEquals([], added)
    assertEquals([muc_self_handle], removed)
    assertEquals([], local_pending)
    assertEquals([], remote_pending)
    assertContains("actor", details)
    assertEquals(bob_handle, details["actor"])
    assertEquals(cs.GC_REASON_KICKED, details["change-reason"])
    assertEquals("bye", details["message"])

    q.expect("dbus-signal", signal="ChannelClosed")
예제 #8
0
def test(q, bus, conn, stream):
    # The user happily joins a MUC
    chan, _, _ = join_muc(q, bus, conn, stream, MUC)
    muc_self_handle = chan.Properties.Get(cs.CHANNEL_IFACE_GROUP, "SelfHandle")
    muc_self_jid = conn.inspect_contact_sync(muc_self_handle)

    # But then Bob kicks us.
    bob_jid = '%s/bob' % MUC
    bob_handle = conn.get_contact_handle_sync(bob_jid)
    stream.send(
        elem('presence', from_=muc_self_jid,
             type='unavailable')(elem(ns.MUC_USER, 'x')(
                 elem('item',
                      affiliation='none', role='none')(elem('actor',
                                                            jid=bob_jid),
                                                       elem('reason')(u'bye')),
                 elem('status', code='307'),
             )))

    mcd_event = q.expect('dbus-signal', signal='MembersChangedDetailed')
    added, removed, local_pending, remote_pending, details = mcd_event.args
    assertEquals([], added)
    assertEquals([muc_self_handle], removed)
    assertEquals([], local_pending)
    assertEquals([], remote_pending)
    assertContains('actor', details)
    assertEquals(bob_handle, details['actor'])
    assertEquals(cs.GC_REASON_KICKED, details['change-reason'])
    assertEquals('bye', details['message'])

    q.expect('dbus-signal', signal='ChannelClosed')
예제 #9
0
 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
예제 #10
0
def test_broken_server(q, bus, conn, stream):
    MUC = 'bro@ken'
    chan, _ , _ = join_muc(q, bus, conn, stream, MUC, affiliation='owner')
    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', {'Private': False})
    e = q.expect('stream-iq', to=MUC, iq_type='get', query_ns=ns.MUC_OWNER)
    handle_muc_owner_get_iq(stream, e.stanza)

    # The server doesn't actually have a form field for configuring whether the
    # room is private or not.
    q.expect('dbus-error', method='UpdateConfiguration', name=cs.SERVICE_CONFUSED)
예제 #11
0
 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
def test_then_disconnect(q, bus, conn, stream):
    room = '*****@*****.**'

    chan, path, props, disco = join_muc(q,
                                        bus,
                                        conn,
                                        stream,
                                        room,
                                        also_capture=[
                                            EventPattern(
                                                'stream-iq',
                                                iq_type='get',
                                                query_name='query',
                                                query_ns=ns.DISCO_INFO,
                                                to=room)
                                        ])

    sync_dbus(bus, q, conn)

    # we call Close...
    call_async(q, chan, 'Close')
    q.expect('dbus-return', method='Close')

    # ...so gabble announces our unavailable presence to the MUC.
    event = q.expect('stream-presence', to=room + '/test')
    elem = event.stanza
    assertEquals('unavailable', elem['type'])

    # oh no, but now we want to disconnect.
    call_async(q, conn, 'Disconnect')

    # the muc factory is told to close everything, so it does so
    # without announcing it to the channel because it does it
    # forcibly, so the channels disappear.
    q.expect_many(EventPattern('dbus-signal', signal='Closed'),
                  EventPattern('dbus-signal', signal='ChannelClosed'))

    # now echo the unavailable presence; this shouldn't be handled
    # because the channel has already closed.
    echo_muc_presence(q, stream, elem, 'none', 'participant')

    # send the stream footer so that the connection thinks it's
    # property disconnected now.
    stream.sendFooter()

    # finally, Disconnect returns
    q.expect('dbus-return', method='Disconnect')
예제 #13
0
def test_broken_server(q, bus, conn, stream):
    MUC = 'bro@ken'
    chan, _, _ = join_muc(q, bus, conn, stream, MUC, affiliation='owner')
    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', {'Private': False})
    e = q.expect('stream-iq', to=MUC, iq_type='get', query_ns=ns.MUC_OWNER)
    handle_muc_owner_get_iq(stream, e.stanza)

    # The server doesn't actually have a form field for configuring whether the
    # room is private or not.
    q.expect('dbus-error',
             method='UpdateConfiguration',
             name=cs.SERVICE_CONFUSED)
def test_then_disconnect(q, bus, conn, stream):
    room = '*****@*****.**'

    chan, path, props, disco = join_muc(q, bus, conn, stream,
            room,
            also_capture=[EventPattern('stream-iq', iq_type='get',
                query_name='query', query_ns=ns.DISCO_INFO, to=room)])

    sync_dbus(bus, q, conn)

    # we call Close...
    call_async(q, chan, 'Close')
    q.expect('dbus-return', method='Close')

    # ...so gabble announces our unavailable presence to the MUC.
    event = q.expect('stream-presence', to=room + '/test')
    elem = event.stanza
    assertEquals('unavailable', elem['type'])

    # oh no, but now we want to disconnect.
    call_async(q, conn, 'Disconnect')

    # the muc factory is told to close everything, so it does so
    # without announcing it to the channel because it does it
    # forcibly, so the channels disappear.
    q.expect_many(EventPattern('dbus-signal', signal='Closed'),
                  EventPattern('dbus-signal', signal='ChannelClosed'))

    # now echo the unavailable presence; this shouldn't be handled
    # because the channel has already closed.
    echo_muc_presence(q, stream, elem, 'none', 'participant')

    # send the stream footer so that the connection thinks it's
    # property disconnected now.
    stream.sendFooter()

    # finally, Disconnect returns
    q.expect('dbus-return', method='Disconnect')
예제 #15
0
def test_subject(q, bus, conn, stream, change_subject, send_first,
        moderator):
    room = '*****@*****.**'

    chan, path, props, disco = join_muc(q, bus, conn, stream,
            room,
            also_capture=[EventPattern('stream-iq', iq_type='get',
                query_name='query', query_ns=ns.DISCO_INFO, to=room)],
            role=(moderator and 'moderator' or 'participant'))

    assert chan.Properties.Get(cs.CHANNEL_IFACE_SUBJECT, "CanSet")

    if send_first:
        # Someone sets a subject.
        message = domish.Element((None, 'message'))
        message['from'] = room + '/bob'
        message['type'] = 'groupchat'
        message.addElement('subject', content='Testing')
        stream.send(message)

        q.expect('dbus-signal', interface=cs.PROPERTIES_IFACE,
                 signal='PropertiesChanged',
                 predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_SUBJECT)
        check_subject_props(chan, 'Testing', room + '/bob', True)

    # Reply to the disco
    iq = make_result_iq(stream, disco.stanza)
    query = iq.firstChildElement()
    feat = query.addElement('feature')
    feat['var'] = 'muc_public'

    x = query.addElement((ns.X_DATA, 'x'))
    x['type'] = 'result'

    if change_subject is not None:
        # When fd.o #13157 has been fixed, this will actually do something.
        field = x.addElement('field')
        field['var'] = 'muc#roomconfig_changesubject'
        field.addElement('value',
                content=(change_subject and 'true' or 'false'))

    stream.send(iq)

    # Someone sets a subject.
    message = domish.Element((None, 'message'))
    message['from'] = room + '/bob'
    message['type'] = 'groupchat'
    message.addElement('subject', content='lalala')
    stream.send(message)

    q.expect('dbus-signal', interface=cs.PROPERTIES_IFACE,
             signal='PropertiesChanged',
             predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_SUBJECT)
    check_subject_props(chan, 'lalala', room + '/bob', True)

    # test changing the subject
    call_async(q, chan, 'SetSubject', 'le lolz', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)

    e = q.expect('stream-message', to=room)
    elem = e.stanza
    assertEquals('groupchat', elem['type'])
    assertEquals(1, len(elem.children))
    assertEquals(elem.children[0].name, 'subject')
    assertEquals(str(elem.children[0]), 'le lolz')

    elem['from'] = room + '/test'
    stream.send(elem)

    q.expect_many(EventPattern('dbus-signal', interface=cs.PROPERTIES_IFACE,
                               signal='PropertiesChanged',
                               predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_SUBJECT),
                  EventPattern('dbus-return', method='SetSubject'),
                 )

    check_subject_props(chan, 'le lolz', room + '/test', True)

    # Test changing the subject and getting an error back.
    call_async(q, chan, 'SetSubject', 'CHICKEN MAN', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)

    e = q.expect('stream-message', to=room)
    elem = e.stanza
    elem['from'] = room
    elem['type'] = 'error'
    error = elem.addElement((None, 'error'))
    error['type'] = 'auth'
    error.addElement((ns.STANZA, 'forbidden'))
    stream.send(elem)
    q.expect('dbus-error', method='SetSubject', name=cs.PERMISSION_DENIED)

    # Test changing the subject and getting an error back which doesn't echo
    # the <subject> element.
    call_async(q, chan, 'SetSubject', 'CHICKEN MAN', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)

    e = q.expect('stream-message', to=room)
    message = domish.Element((None, 'message'))
    message['from'] = room
    message['id'] = e.stanza['id']
    message['type'] = 'error'
    error = message.addElement((None, 'error'))
    error.addElement((ns.STANZA, 'forbidden'))
    stream.send(message)

    q.expect('dbus-error', method='SetSubject', name=cs.PERMISSION_DENIED)

    # Test changing the subject just before we leave the room (and hence not
    # getting a reply). While we're here, check that you can't have more than
    # one call in flight at a time.
    call_async(q, chan, 'SetSubject', 'le lolz', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)
    e = q.expect('stream-message', to=room)

    call_async(q, chan, 'SetSubject', 'le lolz', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)
    q.expect('dbus-error', method='SetSubject', name=cs.NOT_AVAILABLE)

    chan.Close()

    event = q.expect('stream-presence', to=room + '/test')
    elem = event.stanza
    assertEquals('unavailable', elem['type'])

    q.expect('dbus-error', method='SetSubject', name=cs.CANCELLED)

    call_async(q, chan, 'SetSubject', 'how about now?',
        dbus_interface=cs.CHANNEL_IFACE_SUBJECT)
    q.expect('dbus-error', method='SetSubject', name=cs.NOT_AVAILABLE)

    # The MUC confirms that we've left the room.
    echo = make_muc_presence('member', 'none', room, 'test')
    echo['type'] = 'unavailable'
    stream.send(echo)
    q.expect('dbus-signal', signal='ChannelClosed')
예제 #16
0
def test_subject(q, bus, conn, stream, change_subject, send_first,
        moderator):
    # FIXME: fd.o#21152: using many different rooms here because the join_muc()
    # utility function (via request_muc_handle()) only copes with requesting
    # the handle for the first time, due to having to expect the disco#info
    # query to the server and reply to it. Fixing fd.o#21152 will remove the
    # distinction between the first and nth time, at which point we can just
    # join the same room repeatedly.
    global counter
    room = '*****@*****.**' % counter
    counter += 1

    room_handle, chan, path, props, disco = join_muc(q, bus, conn, stream,
            room,
            also_capture=[EventPattern('stream-iq', iq_type='get',
                query_name='query', query_ns=ns.DISCO_INFO, to=room)],
            role=(moderator and 'moderator' or 'participant'))

    # Until the disco returns, we appear to have no properties except subject.

    prop_list = chan.TpProperties.ListProperties()
    props = dict([(name, id) for id, name, sig, flags in prop_list])
    prop_flags = dict([(name, flags) for id, name, sig, flags in prop_list])

    for name in props:
        if name == 'subject':
            # subject can always be changed, until fd.o#13157 is fixed
            assertEquals(cs.PROPERTY_FLAG_WRITE, prop_flags[name])
        else:
            assertEquals(0, prop_flags[name])

    if send_first:
        # Someone sets a subject.
        message = domish.Element((None, 'message'))
        message['from'] = room + '/bob'
        message['type'] = 'groupchat'
        message.addElement('subject', content='Testing')
        stream.send(message)

        q.expect('dbus-signal', signal='PropertiesChanged',
                predicate=lambda e: (props['subject'], 'Testing') in e.args[0])
        e = q.expect('dbus-signal', signal='PropertyFlagsChanged',
                predicate=lambda e:
                    (props['subject'], cs.PROPERTY_FLAGS_RW) in e.args[0])
        assertContains((props['subject-contact'], cs.PROPERTY_FLAG_READ),
                e.args[0])
        assertContains((props['subject-timestamp'], cs.PROPERTY_FLAG_READ),
                e.args[0])

        check_room_props(chan, 'Testing', room + '/bob')

    # Reply to the disco
    iq = make_result_iq(stream, disco.stanza)
    query = iq.firstChildElement()
    x = query.addElement((ns.X_DATA, 'x'))
    x['type'] = 'result'

    feat = x.addElement('feature')
    feat['var'] = 'muc_public'

    if change_subject is not None:
        # When fd.o #13157 has been fixed, this will actually do something.
        field = x.addElement('field')
        field['var'] = 'muc#roomconfig_changesubject'
        field.addElement('value',
                content=(change_subject and 'true' or 'false'))

    stream.send(iq)

    # Someone sets a subject.
    message = domish.Element((None, 'message'))
    message['from'] = room + '/bob'
    message['type'] = 'groupchat'
    message.addElement('subject', content='lalala')
    stream.send(message)

    q.expect('dbus-signal', signal='PropertiesChanged',
            predicate=lambda e: (props['subject'], 'lalala') in e.args[0])

    check_room_props(chan, 'lalala', room + '/bob')

    # if send_first was true, then we already got this
    if not send_first:
        e = q.expect('dbus-signal', signal='PropertyFlagsChanged',
                predicate=lambda e:
                    (props['subject'], cs.PROPERTY_FLAGS_RW) in e.args[0])
        assertContains((props['subject-contact'], cs.PROPERTY_FLAG_READ),
                e.args[0])
        assertContains((props['subject-timestamp'], cs.PROPERTY_FLAG_READ),
                e.args[0])

        check_room_props(chan, 'lalala', room + '/bob')

    chan.Close()

    event = q.expect('stream-presence', to=room + '/test')
    elem = event.stanza
    assertEquals('unavailable', elem['type'])
예제 #17
0
def test_role_changes(q, bus, conn, stream):
    # The test user joins a room. Bob is an owner (and moderator); the test
    # user starts out with no affiliation and the rôle of participant.
    MUC = 'aoeu@snth'
    chan, _, immutable_props, disco = join_muc(q, bus, conn, stream,
        MUC, role='participant',
        also_capture=[
            EventPattern('stream-iq', to=MUC, iq_type='get',
                query_ns=ns.DISCO_INFO),
        ])
    assertContains(cs.CHANNEL_IFACE_ROOM_CONFIG, immutable_props[cs.INTERFACES])

    handle_disco_info_iq(stream, disco.stanza)
    q.expect('dbus-signal', signal='PropertiesChanged',
        args=[cs.CHANNEL_IFACE_ROOM_CONFIG,
              {'ConfigurationRetrieved': True},
              []
             ])

    # If we try to change the configuration, Gabble should say no: it knows
    # we're not allowed to do that.
    call_async(q, chan.RoomConfig1, 'UpdateConfiguration', {})
    q.expect('dbus-error', name=cs.PERMISSION_DENIED)

    config = chan.Properties.GetAll(cs.CHANNEL_IFACE_ROOM_CONFIG)
    assert not config['CanUpdateConfiguration'], config

    # If we acquire affiliation='owner', this should be signalled as our
    # becoming able to modify the channel configuration.
    stream.send(make_muc_presence('owner', 'moderator', MUC, 'test'))
    q.expect('dbus-signal', signal='PropertiesChanged',
        args=[cs.CHANNEL_IFACE_ROOM_CONFIG,
              {'CanUpdateConfiguration': True},
              []
             ])

    # Due to silliness, Gabble has to grab 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)

    # Bob's ownership rights being taken away should have no effect.
    stream.send(make_muc_presence('none', 'participant', MUC, 'bob'))

    # So now we're an owner, and CanUpdateConfiguration is True, we should be
    # able to change some configuration.
    props = dbus.Dictionary(
        { 'Persistent': True,
        }, signature='sv')
    call_async(q, chan.RoomConfig1, 'UpdateConfiguration', props)

    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)

    event = q.expect('stream-iq', to=MUC, iq_type='set', query_ns=ns.MUC_OWNER)
    handle_muc_owner_set_iq(stream, event.stanza,
        {'muc#roomconfig_persistentroom': ['1']})

    q.expect_many(
        EventPattern('dbus-return', method='UpdateConfiguration'),
        EventPattern('dbus-signal', signal='PropertiesChanged',
            args=[cs.CHANNEL_IFACE_ROOM_CONFIG,
                  {'Persistent': True},
                  []
                 ]))

    # If we lose our affiliation, that should be signalled too.
    stream.send(make_muc_presence('none', 'participant', MUC, 'test'))
    q.expect('dbus-signal', signal='PropertiesChanged',
        args=[cs.CHANNEL_IFACE_ROOM_CONFIG,
              {'CanUpdateConfiguration': False},
              []
             ])

    # Gabble should once again reject attempts to change the configuration
    call_async(q, chan.RoomConfig1, 'UpdateConfiguration', {})
    q.expect('dbus-error', name=cs.PERMISSION_DENIED)
예제 #18
0
def test_some_stuff(q, bus, conn, stream):
    text_chan, _, _, disco_iq, owner_iq, _ = join_muc(q, bus, conn, stream,
        '*****@*****.**', role='moderator', affiliation='owner',
        also_capture=[
            EventPattern('stream-iq', to='*****@*****.**', iq_type='get',
                query_ns=ns.DISCO_INFO),
            EventPattern('stream-iq', to='*****@*****.**', iq_type='get',
                query_ns=ns.MUC_OWNER),
            # We discovered that we're an owner. Emitting a signal seems
            # acceptable, although technically this happens before the channel
            # request finishes so the channel could just as well not be on the bus.
            EventPattern('dbus-signal', signal='PropertiesChanged',
                args=[cs.CHANNEL_IFACE_ROOM_CONFIG,
                      {'CanUpdateConfiguration': True},
                      []
                     ]),
        ])

    # This tells Gabble that the MUC is well-behaved and lets owners modify the
    # room description. Technically we could also pull the description out of
    # here, but as an implementation detail we only read configuration out of
    # the disco reply.
    handle_muc_owner_get_iq(stream, owner_iq.stanza)
    pc = q.expect('dbus-signal', signal='PropertiesChanged',
        predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_ROOM_CONFIG)
    _, changed, invalidated = pc.args
    assertEquals(['MutableProperties'], changed.keys())
    assertContains('Description', changed['MutableProperties'])

    handle_disco_info_iq(stream, disco_iq.stanza)
    pc = q.expect('dbus-signal', signal='PropertiesChanged',
        predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_ROOM_CONFIG)
    q.expect('dbus-signal', signal='PropertiesChanged',
        args=[cs.CHANNEL_IFACE_ROOM_CONFIG,
              {'ConfigurationRetrieved': True},
              []
             ])
    _, changed, invalidated = pc.args
    assertEquals(
        { 'Anonymous': True,
          'Moderated': True,
          'Title': ROOM_NAME,
          'Description': ROOM_DESCRIPTION,
          'Private': True,
        }, changed)

    assertEquals([], invalidated)

    config = text_chan.Properties.GetAll(cs.CHANNEL_IFACE_ROOM_CONFIG)

    # Verify that all of the config properties (besides the password ones)
    # correspond to the flags set in handle_disco_info_iq().
    assertEquals(True, config['Anonymous'])
    assertEquals(False, config['InviteOnly'])
    assertEquals(0, config['Limit'])
    assertEquals(True, config['Moderated'])
    assertEquals(ROOM_NAME, config['Title'])
    assertEquals(ROOM_DESCRIPTION, config['Description'])
    assertEquals(False, config['Persistent'])
    assertEquals(True, config['Private'])
    # This is affirmed to be false both by the disco reply and by the muc#owner
    # reply.
    assertEquals(False, config['PasswordProtected'])
    # This comes from the muc#owner reply.
    assertEquals('', config['Password'])

    # We're a room owner, so we should be able to modify the room configuration
    assertEquals(True, config['CanUpdateConfiguration'])
    assertSameSets(
        ['Anonymous',
         'InviteOnly',
        # TODO: when we understand member limit fields, add Limit
         'Moderated',
         'Title',
         'Description',
         'Persistent',
         'Private',
         'PasswordProtected',
         'Password',
        ],
        config['MutableProperties'])

    props = dbus.Dictionary(
        { 'Password': '******',
          'PasswordProtected': True,
        }, signature='sv')
    call_async(q, text_chan.RoomConfig1, 'UpdateConfiguration', props)

    event = q.expect('stream-iq', to='*****@*****.**', iq_type='get',
        query_ns=ns.MUC_OWNER)
    handle_muc_owner_get_iq(stream, event.stanza)

    event = q.expect('stream-iq', to='*****@*****.**', iq_type='set',
        query_ns=ns.MUC_OWNER)
    handle_muc_owner_set_iq(stream, event.stanza,
        {'password': ['foo'],
         'password_protected': ['1'],
        })

    pc, _ = q.expect_many(
        EventPattern('dbus-signal', signal='PropertiesChanged',
            predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_ROOM_CONFIG),
        EventPattern('dbus-return', method='UpdateConfiguration'),
        )

    _, changed, invalidated = pc.args

    assertEquals(props, changed)
    assertEquals([], invalidated)

    config = text_chan.Properties.GetAll(cs.CHANNEL_IFACE_ROOM_CONFIG)
    assertEquals(True, config['PasswordProtected'])
    assertEquals('foo', config['Password'])

    # Check unknown fields are rejected.
    props = dbus.Dictionary(
        { 'PasswordProtected': True,
          'Riding on a donkey': True,
        }, signature='sv')
    call_async(q, text_chan.RoomConfig1, 'UpdateConfiguration', props)
    q.expect('dbus-error', name=cs.INVALID_ARGUMENT)

    # Check that mis-typed fields are rejected.
    props = dbus.Dictionary(
        { 'PasswordProtected': 'foo',
          'Password': True,
        }, signature='sv')
    call_async(q, text_chan.RoomConfig1, 'UpdateConfiguration', props)
    q.expect('dbus-error', name=cs.INVALID_ARGUMENT)

    # Updating no fields should be a no-op, and not wait on any network
    # traffic.
    text_chan.RoomConfig1.UpdateConfiguration({})
예제 #19
0
def test(q, bus, conn, stream):
    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_muc(q, bus, conn, stream, '*****@*****.**')

    # bob offers a stream tube
    stream_tube_id = 1

    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'))
    stream.send(presence)

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

    e = q.expect('dbus-signal', signal='NewChannels',
                 predicate=new_chan_predicate)
    channels = e.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE

    tube_chan = bus.get_object(conn.bus_name, path)
    tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)

    call_async(q, tube_iface, 'Accept', 0, 0, '',
        byte_arrays=True)

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

    unix_socket_adr = accept_return_event.value[0]

    factory = EventProtocolClientFactory(q)
    reactor.connectUNIX(unix_socket_adr, factory)

     # expect SI request
    e = q.expect('stream-iq', to='[email protected]/bob', query_ns=ns.SI,
        query_name='si')

    bytestream, profile = create_from_si_offer(stream, q, BytestreamS5BRelay, e.stanza,
        '[email protected]/bob')

    result, si = bytestream.create_si_reply(e.stanza, 'test@localhost/Resource')
    si.addElement((ns.TUBES, 'tube'))
    stream.send(result)

    # wait SOCKS5 init iq
    id, mode, si, hosts = bytestream._expect_socks5_init()
    for jid, host, port in hosts:
        # the proxy is not announced because we are in a muc
        assert jid != 'proxy.localhost'
def test(q, bus, conn, stream):
    iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard')

    acknowledge_iq(stream, iq_event.stanza)
    t.check_conn_properties(q, conn)

    # Create new style tube channel and make sure that is indeed
    # returned.
    muc = '*****@*****.**'

    call_async(q, conn.Requests, 'CreateChannel',
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
          cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
          cs.TARGET_ID: muc,
          cs.DBUS_TUBE_SERVICE_NAME: 'com.example.LolDongs'})

    q.expect('stream-presence', to='%s/test' % muc)
    stream.send(make_muc_presence('owner', 'moderator', muc, 'bob'))
    stream.send(make_muc_presence('none', 'participant', muc, 'test'))

    ret, _, _ = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
        )

    _, props = ret.value

    assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_DBUS_TUBE)
    assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM)
    assertEquals(props[cs.TARGET_ID], muc)

    # Now try joining the text muc before asking for the tube channel.
    muc = '*****@*****.**'

    join_muc(q, bus, conn, stream, muc)

    call_async(q, conn.Requests, 'CreateChannel',
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
          cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
          cs.TARGET_ID: muc,
          cs.DBUS_TUBE_SERVICE_NAME: 'com.example.LolDongs'})

    ret, _, _ = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
        )

    _, props = ret.value

    assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_DBUS_TUBE)
    assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM)
    assertEquals(props[cs.TARGET_ID], muc)

    # Now make sure we can get our Tubes channel if we request it.
    muc = '*****@*****.**'

    call_async(q, conn.Requests, 'CreateChannel',
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TUBES,
          cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
          cs.TARGET_ID: muc})

    q.expect('stream-presence', to='%s/test' % muc)
    stream.send(make_muc_presence('owner', 'moderator', muc, 'bob'))
    stream.send(make_muc_presence('none', 'participant', muc, 'test'))

    ret, _, _ = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
        )

    _, props = ret.value

    assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_TUBES)
    assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM)
    assertEquals(props[cs.TARGET_ID], muc)
예제 #21
0
def test(q, bus, conn, stream, access_control):
    iq_event = q.expect("stream-iq", to=None, query_ns="vcard-temp", query_name="vCard")

    acknowledge_iq(stream, iq_event.stanza)

    # check if we can request muc D-Bus tube
    t.check_conn_properties(q, conn)

    self_handle = conn.GetSelfHandle()
    self_name = conn.InspectHandles(1, [self_handle])[0]

    handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn, stream, "*****@*****.**")

    # Exercise basic Channel Properties from spec 0.17.7
    channel_props = tubes_chan.GetAll(cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE)
    assert channel_props.get("TargetHandle") == handle, (channel_props.get("TargetHandle"), handle)
    assert channel_props.get("TargetHandleType") == 2, channel_props.get("TargetHandleType")
    assert channel_props.get("ChannelType") == cs.CHANNEL_TYPE_TUBES, channel_props.get("ChannelType")
    assert "Interfaces" in channel_props, channel_props
    assert cs.CHANNEL_IFACE_GROUP in channel_props["Interfaces"], channel_props["Interfaces"]
    assert channel_props["TargetID"] == "*****@*****.**", channel_props
    assert channel_props["Requested"] == True
    assert channel_props["InitiatorID"] == "test@localhost"
    assert channel_props["InitiatorHandle"] == conn.GetSelfHandle()

    # Exercise Group Properties from spec 0.17.6 (in a basic way)
    group_props = tubes_chan.GetAll(cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE)
    assert "SelfHandle" in group_props, group_props
    assert "HandleOwners" in group_props, group_props
    assert "Members" in group_props, group_props
    assert "LocalPendingMembers" in group_props, group_props
    assert "RemotePendingMembers" in group_props, group_props
    assert "GroupFlags" in group_props, group_props

    tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP)
    assert group_props["SelfHandle"] == tubes_self_handle

    # Offer a D-Bus tube (old API)
    call_async(q, tubes_iface, "OfferDBusTube", "com.example.TestCase", sample_parameters)

    new_tube_event, presence_event, offer_return_event, dbus_changed_event = q.expect_many(
        EventPattern("dbus-signal", signal="NewTube"),
        EventPattern("stream-presence", to="[email protected]/test"),
        EventPattern("dbus-return", method="OfferDBusTube"),
        EventPattern("dbus-signal", signal="DBusNamesChanged", interface=cs.CHANNEL_TYPE_TUBES),
    )

    # handle new_tube_event
    dbus_tube_id = new_tube_event.args[0]
    assert new_tube_event.args[1] == tubes_self_handle
    assert new_tube_event.args[2] == cs.TUBE_TYPE_DBUS
    assert new_tube_event.args[3] == "com.example.TestCase"
    assert new_tube_event.args[4] == sample_parameters
    assert new_tube_event.args[5] == cs.TUBE_STATE_OPEN

    # handle offer_return_event
    assert offer_return_event.value[0] == dbus_tube_id

    # handle presence_event
    # We announce our newly created tube in our muc presence
    presence = presence_event.stanza
    dbus_stream_id, my_bus_name = check_tube_in_presence(presence, dbus_tube_id, "[email protected]/test")

    # handle dbus_changed_event
    assert dbus_changed_event.args[0] == dbus_tube_id
    assert dbus_changed_event.args[1][0][0] == tubes_self_handle
    assert dbus_changed_event.args[1][0][1] == my_bus_name

    # handle offer_return_event
    assert dbus_tube_id == offer_return_event.value[0]

    tubes = tubes_iface.ListTubes(byte_arrays=True)
    assert len(tubes) == 1
    expected_tube = (
        dbus_tube_id,
        tubes_self_handle,
        cs.TUBE_TYPE_DBUS,
        "com.example.TestCase",
        sample_parameters,
        cs.TUBE_STATE_OPEN,
    )
    t.check_tube_in_tubes(expected_tube, tubes)

    dbus_tube_adr = tubes_iface.GetDBusTubeAddress(dbus_tube_id)
    tube = Connection(dbus_tube_adr)
    fire_signal_on_tube(q, tube, "*****@*****.**", dbus_stream_id, my_bus_name)

    # offer a D-Bus tube to another room using new API
    muc = "*****@*****.**"
    request = {
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
        cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
        cs.TARGET_ID: "*****@*****.**",
        cs.DBUS_TUBE_SERVICE_NAME: "com.example.TestCase",
    }
    join_muc(q, bus, conn, stream, muc, request=request)

    # The order in which the NewChannels signals are fired is
    # undefined -- it could be the (tubes, text) channels first, or it
    # could be the tube channel first; so let's accept either order
    # here.

    first, second = q.expect_many(
        EventPattern("dbus-signal", signal="NewChannels"), EventPattern("dbus-signal", signal="NewChannels")
    )

    # NewChannels signal with the text and tubes channels together.
    def nc_textandtubes(event):
        channels = event.args[0]
        assert len(channels) == 2
        path1, prop1 = channels[0]
        path2, prop2 = channels[1]
        assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES]

        got_text, got_tubes = False, False
        for path, props in channels:
            if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT:
                got_text = True

                text_chan = dbus.Interface(bus.get_object(conn.bus_name, path), cs.CHANNEL)
            elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES:
                got_tubes = True

                tubes_iface = dbus.Interface(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_TUBES)
            else:
                assert False

            assert props[cs.INITIATOR_HANDLE] == self_handle
            assert props[cs.INITIATOR_ID] == self_name
            assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES]
            assert props[cs.TARGET_ID] == "*****@*****.**"
            assert props[cs.REQUESTED] == False

        assert (got_text, got_tubes) == (True, True)

        return text_chan

    # NewChannels signal with the tube channel.
    def nc_tube(event):
        # FIXME: in this case, all channels should probably be announced together
        channels = event.args[0]
        assert len(channels) == 1
        path, prop = channels[0]
        assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
        assert prop[cs.INITIATOR_ID] == "[email protected]/test"
        assert prop[cs.REQUESTED] == True
        assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
        assert prop[cs.TARGET_ID] == "*****@*****.**"
        assert prop[cs.DBUS_TUBE_SERVICE_NAME] == "com.example.TestCase"
        assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [
            cs.SOCKET_ACCESS_CONTROL_CREDENTIALS,
            cs.SOCKET_ACCESS_CONTROL_LOCALHOST,
        ]

        return path, prop

    if len(first.args[0]) == 1:
        path, prop = nc_tube(first)
        text_chan = nc_textandtubes(second)
    else:
        text_chan = nc_textandtubes(first)
        path, prop = nc_tube(second)

    # check that the tube channel is in the channels list
    all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, "Channels", dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True)
    assertContains((path, prop), all_channels)

    tube_chan = bus.get_object(conn.bus_name, path)
    dbus_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE)
    chan_iface = dbus.Interface(tube_chan, cs.CHANNEL)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True)

    assert tube_props["State"] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED

    # try to offer using a wrong access control
    try:
        dbus_tube_iface.Offer(sample_parameters, cs.SOCKET_ACCESS_CONTROL_PORT)
    except dbus.DBusException, e:
        assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
def test(q, bus, conn, stream, access_control):
    conn.Connect()

    _, iq_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'))

    acknowledge_iq(stream, iq_event.stanza)

    # check if we can request muc D-Bus tube
    t.check_conn_properties(q, conn)

    self_handle = conn.GetSelfHandle()
    self_name = conn.InspectHandles(1, [self_handle])[0]

    handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn,
        stream, '*****@*****.**')

    # Exercise basic Channel Properties from spec 0.17.7
    channel_props = tubes_chan.GetAll(cs.CHANNEL,
            dbus_interface=dbus.PROPERTIES_IFACE)
    assert channel_props.get('TargetHandle') == handle,\
            (channel_props.get('TargetHandle'), handle)
    assert channel_props.get('TargetHandleType') == 2,\
            channel_props.get('TargetHandleType')
    assert channel_props.get('ChannelType') == cs.CHANNEL_TYPE_TUBES,\
            channel_props.get('ChannelType')
    assert 'Interfaces' in channel_props, channel_props
    assert cs.CHANNEL_IFACE_GROUP in channel_props['Interfaces'], \
            channel_props['Interfaces']
    assert channel_props['TargetID'] == '*****@*****.**', channel_props
    assert channel_props['Requested'] == True
    assert channel_props['InitiatorID'] == 'test@localhost'
    assert channel_props['InitiatorHandle'] == conn.GetSelfHandle()

    # Exercise Group Properties from spec 0.17.6 (in a basic way)
    group_props = tubes_chan.GetAll(cs.CHANNEL_IFACE_GROUP,
            dbus_interface=dbus.PROPERTIES_IFACE)
    assert 'SelfHandle' in group_props, group_props
    assert 'HandleOwners' in group_props, group_props
    assert 'Members' in group_props, group_props
    assert 'LocalPendingMembers' in group_props, group_props
    assert 'RemotePendingMembers' in group_props, group_props
    assert 'GroupFlags' in group_props, group_props

    tubes_self_handle = tubes_chan.GetSelfHandle(
        dbus_interface=cs.CHANNEL_IFACE_GROUP)
    assert group_props['SelfHandle'] == tubes_self_handle

    # Offer a D-Bus tube (old API)
    call_async(q, tubes_iface, 'OfferDBusTube',
            'com.example.TestCase', sample_parameters)

    new_tube_event, presence_event, offer_return_event, dbus_changed_event = \
        q.expect_many(
        EventPattern('dbus-signal', signal='NewTube'),
        EventPattern('stream-presence', to='[email protected]/test'),
        EventPattern('dbus-return', method='OfferDBusTube'),
        EventPattern('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_TUBES))

    # handle new_tube_event
    dbus_tube_id = new_tube_event.args[0]
    assert new_tube_event.args[1] == tubes_self_handle
    assert new_tube_event.args[2] == cs.TUBE_TYPE_DBUS
    assert new_tube_event.args[3] == 'com.example.TestCase'
    assert new_tube_event.args[4] == sample_parameters
    assert new_tube_event.args[5] == cs.TUBE_STATE_OPEN

    # handle offer_return_event
    assert offer_return_event.value[0] == dbus_tube_id

    # handle presence_event
    # We announce our newly created tube in our muc presence
    presence = presence_event.stanza
    dbus_stream_id, my_bus_name = check_tube_in_presence(presence, dbus_tube_id, '[email protected]/test')

    # handle dbus_changed_event
    assert dbus_changed_event.args[0] == dbus_tube_id
    assert dbus_changed_event.args[1][0][0] == tubes_self_handle
    assert dbus_changed_event.args[1][0][1] == my_bus_name

    # handle offer_return_event
    assert dbus_tube_id == offer_return_event.value[0]

    tubes = tubes_iface.ListTubes(byte_arrays=True)
    assert len(tubes) == 1
    expected_tube = (dbus_tube_id, tubes_self_handle, cs.TUBE_TYPE_DBUS,
        'com.example.TestCase', sample_parameters, cs.TUBE_STATE_OPEN)
    t.check_tube_in_tubes(expected_tube, tubes)

    dbus_tube_adr = tubes_iface.GetDBusTubeAddress(dbus_tube_id)
    tube = Connection(dbus_tube_adr)
    fire_signal_on_tube(q, tube, '*****@*****.**', dbus_stream_id, my_bus_name)

    # offer a D-Bus tube to another room using new API
    muc = '*****@*****.**'
    request = {
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
        cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
        cs.TARGET_ID: '*****@*****.**',
        cs.DBUS_TUBE_SERVICE_NAME: 'com.example.TestCase',
    }
    join_muc(q, bus, conn, stream, muc, request=request)

    # first text and tubes channels are announced
    event = q.expect('dbus-signal', signal='NewChannels')
    channels = event.args[0]
    assert len(channels) == 2
    path1, prop1 = channels[0]
    path2, prop2 = channels[1]
    assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == \
        [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES]

    got_text, got_tubes = False, False
    for path, props in channels:
        if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT:
            got_text = True

            text_chan = dbus.Interface(bus.get_object(conn.bus_name, path),
                cs.CHANNEL)
        elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES:
            got_tubes = True

            tubes_iface = dbus.Interface(bus.get_object(conn.bus_name, path),
                cs.CHANNEL_TYPE_TUBES)
        else:
            assert False

        assert props[cs.INITIATOR_HANDLE] == self_handle
        assert props[cs.INITIATOR_ID] == self_name
        assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES]
        assert props[cs.TARGET_ID] == '*****@*****.**'
        assert props[cs.REQUESTED] == False

    assert (got_text, got_tubes) == (True, True)

    # now the tube channel is announced
    # FIXME: in this case, all channels should probably be announced together
    event = q.expect('dbus-signal', signal='NewChannels')
    channels = event.args[0]
    assert len(channels) == 1
    path, prop = channels[0]
    assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
    assert prop[cs.INITIATOR_ID] == '[email protected]/test'
    assert prop[cs.REQUESTED] == True
    assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
    assert prop[cs.TARGET_ID] == '*****@*****.**'
    assert prop[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
    assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [cs.SOCKET_ACCESS_CONTROL_CREDENTIALS,
        cs.SOCKET_ACCESS_CONTROL_LOCALHOST]

    # check that the tube channel is in the channels list
    all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels',
        dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True)
    assertContains((path, prop), all_channels)

    tube_chan = bus.get_object(conn.bus_name, path)
    dbus_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE)
    chan_iface = dbus.Interface(tube_chan, cs.CHANNEL)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE,
        byte_arrays=True)

    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED

    # try to offer using a wrong access control
    try:
        dbus_tube_iface.Offer(sample_parameters, cs.SOCKET_ACCESS_CONTROL_PORT)
    except dbus.DBusException, e:
        assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
def test(q, bus, conn, stream):
    expect_and_handle_get_vcard(q, stream)

    jid = u'*****@*****.**'
    alias = u'Horza'
    handle = conn.get_contact_handle_sync(jid)

    # We don't have an interesting alias for Horza
    assertEquals({handle: jid}, get_aliases(conn, [handle]))

    # Horza sends us a message containing his preferred nickname.
    stream.send(
        elem('message', from_=jid,
             type='chat')(elem('body')(u"It's a long story."),
                          elem(ns.NICK, 'nick')(alias)))
    _, mr = q.expect_many(
        EventPattern('dbus-signal',
                     signal='AliasesChanged',
                     args=[[(handle, alias)]]),
        EventPattern('dbus-signal', signal='MessageReceived'),
    )

    channel = wrap_channel(bus.get_object(conn.bus_name, mr.path), 'Text')

    # So now we know his alias.
    assertEquals({handle: alias}, get_aliases(conn, [handle]))

    # Presumably to avoid non-contacts being able to make Gabble's memory
    # footprint grow forever, Gabble throws the alias away when we close the
    # channel.
    header = mr.args[0][0]
    channel.Text.AcknowledgePendingMessages([header['pending-message-id']])
    channel.Close()

    # FIXME: Gabble forgets the alias, but it doesn't signal that it has done
    # so; it probably should.
    # q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, jid)]])
    assertEquals({handle: jid}, get_aliases(conn, [handle]))

    # Basically the same test, but in a MUC.
    #
    # It's a bit questionable whether this ought to work.
    # <http://xmpp.org/extensions/xep-0172.html#muc> doesn't have anything to
    # say about including <nick/> in messages; it does talk about including
    # <nick> in your MUC presence, which is actually equally sketchy! If I join
    # a muc with the resource '/wjt', and you join with resource '/ohai' but
    # say that your nickname is 'wjt', what on earth is Alice's UI supposed to
    # show when you send a message?
    #
    # But anyway, at the time of writing this "works", so I'm adding a test to
    # make it explicit.  Perhaps in future we might change this test to verify
    # that it doesn't "work".
    room_jid = '*****@*****.**'
    muc, _, _ = join_muc(q, bus, conn, stream, room_jid)

    bob_jid = room_jid + '/bob'
    bob_handle = conn.get_contact_handle_sync(bob_jid)

    assertEquals({bob_handle: 'bob'}, get_aliases(conn, [bob_handle]))

    stream.send(
        elem('message', from_=bob_jid, type='groupchat')(
            elem('body')(u'My religion dies with me.'),
            elem(ns.NICK, 'nick')(alias),
        ))

    q.expect_many(
        EventPattern('dbus-signal',
                     signal='AliasesChanged',
                     args=[[(bob_handle, alias)]]),
        EventPattern('dbus-signal', signal='MessageReceived'),
    )

    assertEquals({bob_handle: alias}, get_aliases(conn, [bob_handle]))

    muc.Close()
    q.expect('stream-presence', to=room_jid + '/test')
    echo = make_muc_presence('member', 'none', room_jid, 'test')
    echo['type'] = 'unavailable'
    stream.send(echo)
    q.expect('dbus-signal', signal='ChannelClosed')

    # FIXME: Gabble forgets the alias, but it doesn't signal that it has done
    # so; it probably should.
    # q.expect('dbus-signal', signal='AliasesChanged',
    #     args=[[(bob_handle, 'bob')]])
    assertEquals({bob_handle: 'bob'}, get_aliases(conn, [bob_handle]))
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 = q.expect('stream-iq',
                        to=None,
                        query_ns='vcard-temp',
                        query_name='vCard')

    acknowledge_iq(stream, iq_event.stanza)

    t.check_conn_properties(q, conn)

    bob_handle = conn.get_contact_handle_sync('[email protected]/bob')

    address = t.create_server(q, address_type)

    def new_chan_predicate(e):
        types = []
        for _, props in e.args[0]:
            types.append(props[cs.CHANNEL_TYPE])

        return cs.CHANNEL_TYPE_STREAM_TUBE in types

    def find_stream_tube(channels):
        for path, props in channels:
            if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE:
                return path, props

        return None, None

    # offer a stream tube to another room (new API)
    address = t.create_server(q, address_type, block_reading=True)

    request = {
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
        cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
        cs.TARGET_ID: '*****@*****.**',
        cs.STREAM_TUBE_SERVICE: 'newecho',
    }
    _, new_tube_path, new_tube_props = \
        join_muc(q, bus, conn, stream, '*****@*****.**', request)

    e = q.expect('dbus-signal',
                 signal='NewChannels',
                 predicate=new_chan_predicate)

    path, prop = find_stream_tube(e.args[0])
    assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
    assert prop[cs.INITIATOR_ID] == '[email protected]/test'
    assert prop[cs.REQUESTED] == True
    assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
    assert prop[cs.TARGET_ID] == '*****@*****.**'
    assert prop[cs.STREAM_TUBE_SERVICE] == 'newecho'

    # check that the tube channel is in the channels list
    all_channels = conn.Get(cs.CONN_IFACE_REQUESTS,
                            'Channels',
                            dbus_interface=cs.PROPERTIES_IFACE,
                            byte_arrays=True)
    assertContains((path, prop), all_channels)

    tube_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamTube')
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE,
                                  dbus_interface=cs.PROPERTIES_IFACE)

    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED

    # offer the tube
    call_async(q, tube_chan.StreamTube, 'Offer', address_type, address,
               access_control, {'foo': 'bar'})

    stream_event, _, status_event = q.expect_many(
        EventPattern('stream-presence',
                     to='[email protected]/test',
                     predicate=lambda e: t.presence_contains_tube(e)),
        EventPattern('dbus-return', method='Offer'),
        EventPattern('dbus-signal',
                     signal='TubeChannelStateChanged',
                     args=[cs.TUBE_CHANNEL_STATE_OPEN]))

    tube_self_handle = tube_chan.Properties.Get(cs.CHANNEL_IFACE_GROUP,
                                                'SelfHandle')
    assert conn.inspect_contact_sync(
        tube_self_handle) == '[email protected]/test'

    presence = stream_event.stanza
    tubes_nodes = xpath.queryForNodes(
        '/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence)
    assert tubes_nodes is not None
    assert len(tubes_nodes) == 1

    stream_tube_id = 666

    tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0])
    assert tube_nodes is not None
    assert len(tube_nodes) == 1
    for tube in tube_nodes:
        assert tube['type'] == 'stream'
        assert not tube.hasAttribute('initiator')
        assert tube['service'] == 'newecho'
        assert not tube.hasAttribute('stream-id')
        assert not tube.hasAttribute('dbus-name')

        stream_tube_id = int(tube['id'])

    params = {}
    parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube)
    for node in parameter_nodes:
        assert node['name'] not in params
        params[node['name']] = (node['type'], str(node))
    assert params == {'foo': ('str', 'bar')}

    bob_handle = conn.get_contact_handle_sync('[email protected]/bob')

    bytestream = connect_to_tube(stream, q, bytestream_cls,
                                 '*****@*****.**', stream_tube_id)

    iq_event, socket_event, conn_event = q.expect_many(
        EventPattern('stream-iq', iq_type='result'),
        EventPattern('socket-connected'),
        EventPattern('dbus-signal',
                     signal='NewRemoteConnection',
                     interface=cs.CHANNEL_TYPE_STREAM_TUBE))

    handle, access, conn_id = conn_event.args
    assert handle == bob_handle

    protocol = socket_event.protocol
    # start to read from the transport so we can read the control byte
    protocol.transport.startReading()
    t.check_new_connection_access(q, access_control, access, protocol)

    # handle iq_event
    bytestream.check_si_reply(iq_event.stanza)
    tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES,
                               iq_event.stanza)
    assert len(tube) == 1

    use_tube(q, bytestream, protocol, conn_id)

    tube_chan.Channel.Close()
    q.expect_many(EventPattern('dbus-signal', signal='Closed'),
                  EventPattern('dbus-signal', signal='ChannelClosed'))

    t.cleanup()
예제 #25
0
def test_subject(q, bus, conn, stream, change_subject, send_first,
        moderator):
    room = '*****@*****.**'

    room_handle, chan, path, props, disco = join_muc(q, bus, conn, stream,
            room,
            also_capture=[EventPattern('stream-iq', iq_type='get',
                query_name='query', query_ns=ns.DISCO_INFO, to=room)],
            role=(moderator and 'moderator' or 'participant'))

    assert chan.Properties.Get(cs.CHANNEL_IFACE_SUBJECT, "CanSet")

    if send_first:
        # Someone sets a subject.
        message = domish.Element((None, 'message'))
        message['from'] = room + '/bob'
        message['type'] = 'groupchat'
        message.addElement('subject', content='Testing')
        stream.send(message)

        q.expect('dbus-signal', interface=cs.PROPERTIES_IFACE,
                 signal='PropertiesChanged',
                 predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_SUBJECT)
        check_subject_props(chan, 'Testing', room + '/bob', True)

    # Reply to the disco
    iq = make_result_iq(stream, disco.stanza)
    query = iq.firstChildElement()
    feat = query.addElement('feature')
    feat['var'] = 'muc_public'

    x = query.addElement((ns.X_DATA, 'x'))
    x['type'] = 'result'

    if change_subject is not None:
        # When fd.o #13157 has been fixed, this will actually do something.
        field = x.addElement('field')
        field['var'] = 'muc#roomconfig_changesubject'
        field.addElement('value',
                content=(change_subject and 'true' or 'false'))

    stream.send(iq)

    # Someone sets a subject.
    message = domish.Element((None, 'message'))
    message['from'] = room + '/bob'
    message['type'] = 'groupchat'
    message.addElement('subject', content='lalala')
    stream.send(message)

    q.expect('dbus-signal', interface=cs.PROPERTIES_IFACE,
             signal='PropertiesChanged',
             predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_SUBJECT)
    check_subject_props(chan, 'lalala', room + '/bob', True)

    # test changing the subject
    call_async(q, chan, 'SetSubject', 'le lolz', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)

    e = q.expect('stream-message', to=room)
    elem = e.stanza
    assertEquals('groupchat', elem['type'])
    assertEquals(1, len(elem.children))
    assertEquals(elem.children[0].name, 'subject')
    assertEquals(str(elem.children[0]), 'le lolz')

    elem['from'] = room + '/test'
    stream.send(elem)

    q.expect_many(EventPattern('dbus-signal', interface=cs.PROPERTIES_IFACE,
                               signal='PropertiesChanged',
                               predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_SUBJECT),
                  EventPattern('dbus-return', method='SetSubject'),
                 )

    check_subject_props(chan, 'le lolz', room + '/test', True)

    # Test changing the subject and getting an error back.
    call_async(q, chan, 'SetSubject', 'CHICKEN MAN', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)

    e = q.expect('stream-message', to=room)
    elem = e.stanza
    elem['from'] = room
    elem['type'] = 'error'
    error = elem.addElement((None, 'error'))
    error['type'] = 'auth'
    error.addElement((ns.STANZA, 'forbidden'))
    stream.send(elem)
    q.expect('dbus-error', method='SetSubject', name=cs.PERMISSION_DENIED)

    # Test changing the subject and getting an error back which doesn't echo
    # the <subject> element.
    call_async(q, chan, 'SetSubject', 'CHICKEN MAN', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)

    e = q.expect('stream-message', to=room)
    message = domish.Element((None, 'message'))
    message['from'] = room
    message['id'] = e.stanza['id']
    message['type'] = 'error'
    error = message.addElement((None, 'error'))
    error.addElement((ns.STANZA, 'forbidden'))
    stream.send(message)

    q.expect('dbus-error', method='SetSubject', name=cs.PERMISSION_DENIED)

    # Test changing the subject just before we leave the room (and hence not
    # getting a reply). While we're here, check that you can't have more than
    # one call in flight at a time.
    call_async(q, chan, 'SetSubject', 'le lolz', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)
    e = q.expect('stream-message', to=room)

    call_async(q, chan, 'SetSubject', 'le lolz', dbus_interface=cs.CHANNEL_IFACE_SUBJECT)
    q.expect('dbus-error', method='SetSubject', name=cs.NOT_AVAILABLE)

    chan.Close()

    event = q.expect('stream-presence', to=room + '/test')
    elem = event.stanza
    assertEquals('unavailable', elem['type'])

    q.expect('dbus-error', method='SetSubject', name=cs.CANCELLED)

    call_async(q, chan, 'SetSubject', 'how about now?',
        dbus_interface=cs.CHANNEL_IFACE_SUBJECT)
    q.expect('dbus-error', method='SetSubject', name=cs.NOT_AVAILABLE)

    # The MUC confirms that we've left the room.
    echo = make_muc_presence('member', 'none', room, 'test')
    echo['type'] = 'unavailable'
    stream.send(echo)
    q.expect('dbus-signal', signal='ChannelClosed')
예제 #26
0
def test_some_stuff(q, bus, conn, stream):
    text_chan, _, _, disco_iq, owner_iq, _ = join_muc(
        q,
        bus,
        conn,
        stream,
        '*****@*****.**',
        role='moderator',
        affiliation='owner',
        also_capture=[
            EventPattern('stream-iq',
                         to='*****@*****.**',
                         iq_type='get',
                         query_ns=ns.DISCO_INFO),
            EventPattern('stream-iq',
                         to='*****@*****.**',
                         iq_type='get',
                         query_ns=ns.MUC_OWNER),
            # We discovered that we're an owner. Emitting a signal seems
            # acceptable, although technically this happens before the channel
            # request finishes so the channel could just as well not be on the bus.
            EventPattern('dbus-signal',
                         signal='PropertiesChanged',
                         args=[
                             cs.CHANNEL_IFACE_ROOM_CONFIG, {
                                 'CanUpdateConfiguration': True
                             }, []
                         ]),
        ])

    # This tells Gabble that the MUC is well-behaved and lets owners modify the
    # room description. Technically we could also pull the description out of
    # here, but as an implementation detail we only read configuration out of
    # the disco reply.
    handle_muc_owner_get_iq(stream, owner_iq.stanza)
    pc = q.expect(
        'dbus-signal',
        signal='PropertiesChanged',
        predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_ROOM_CONFIG)
    _, changed, invalidated = pc.args
    assertEquals(['MutableProperties'], changed.keys())
    assertContains('Description', changed['MutableProperties'])

    handle_disco_info_iq(stream, disco_iq.stanza)
    pc = q.expect(
        'dbus-signal',
        signal='PropertiesChanged',
        predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_ROOM_CONFIG)
    q.expect('dbus-signal',
             signal='PropertiesChanged',
             args=[
                 cs.CHANNEL_IFACE_ROOM_CONFIG, {
                     'ConfigurationRetrieved': True
                 }, []
             ])
    _, changed, invalidated = pc.args
    assertEquals(
        {
            'Anonymous': True,
            'Moderated': True,
            'Title': ROOM_NAME,
            'Description': ROOM_DESCRIPTION,
            'Private': True,
        }, changed)

    assertEquals([], invalidated)

    config = text_chan.Properties.GetAll(cs.CHANNEL_IFACE_ROOM_CONFIG)

    # Verify that all of the config properties (besides the password ones)
    # correspond to the flags set in handle_disco_info_iq().
    assertEquals(True, config['Anonymous'])
    assertEquals(False, config['InviteOnly'])
    assertEquals(0, config['Limit'])
    assertEquals(True, config['Moderated'])
    assertEquals(ROOM_NAME, config['Title'])
    assertEquals(ROOM_DESCRIPTION, config['Description'])
    assertEquals(False, config['Persistent'])
    assertEquals(True, config['Private'])
    # This is affirmed to be false both by the disco reply and by the muc#owner
    # reply.
    assertEquals(False, config['PasswordProtected'])
    # This comes from the muc#owner reply.
    assertEquals('', config['Password'])

    # We're a room owner, so we should be able to modify the room configuration
    assertEquals(True, config['CanUpdateConfiguration'])
    assertSameSets(
        [
            'Anonymous',
            'InviteOnly',
            # TODO: when we understand member limit fields, add Limit
            'Moderated',
            'Title',
            'Description',
            'Persistent',
            'Private',
            'PasswordProtected',
            'Password',
        ],
        config['MutableProperties'])

    props = dbus.Dictionary({
        'Password': '******',
        'PasswordProtected': True,
    },
                            signature='sv')
    call_async(q, text_chan.RoomConfig1, 'UpdateConfiguration', props)

    event = q.expect('stream-iq',
                     to='*****@*****.**',
                     iq_type='get',
                     query_ns=ns.MUC_OWNER)
    handle_muc_owner_get_iq(stream, event.stanza)

    event = q.expect('stream-iq',
                     to='*****@*****.**',
                     iq_type='set',
                     query_ns=ns.MUC_OWNER)
    handle_muc_owner_set_iq(stream, event.stanza, {
        'password': ['foo'],
        'password_protected': ['1'],
    })

    pc, _ = q.expect_many(
        EventPattern(
            'dbus-signal',
            signal='PropertiesChanged',
            predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_ROOM_CONFIG),
        EventPattern('dbus-return', method='UpdateConfiguration'),
    )

    _, changed, invalidated = pc.args

    assertEquals(props, changed)
    assertEquals([], invalidated)

    config = text_chan.Properties.GetAll(cs.CHANNEL_IFACE_ROOM_CONFIG)
    assertEquals(True, config['PasswordProtected'])
    assertEquals('foo', config['Password'])

    # Check unknown fields are rejected.
    props = dbus.Dictionary(
        {
            'PasswordProtected': True,
            'Riding on a donkey': True,
        },
        signature='sv')
    call_async(q, text_chan.RoomConfig1, 'UpdateConfiguration', props)
    q.expect('dbus-error', name=cs.INVALID_ARGUMENT)

    # Check that mis-typed fields are rejected.
    props = dbus.Dictionary({
        'PasswordProtected': 'foo',
        'Password': True,
    },
                            signature='sv')
    call_async(q, text_chan.RoomConfig1, 'UpdateConfiguration', props)
    q.expect('dbus-error', name=cs.INVALID_ARGUMENT)

    # Updating no fields should be a no-op, and not wait on any network
    # traffic.
    text_chan.RoomConfig1.UpdateConfiguration({})
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 = q.expect('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard')

    acknowledge_iq(stream, iq_event.stanza)

    t.check_conn_properties(q, conn)

    bob_handle = conn.get_contact_handle_sync('[email protected]/bob')

    address = t.create_server(q, address_type)

    def new_chan_predicate(e):
        types = []
        for _, props in e.args[0]:
            types.append(props[cs.CHANNEL_TYPE])

        return cs.CHANNEL_TYPE_STREAM_TUBE in types

    def find_stream_tube(channels):
        for path, props in channels:
            if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE:
                return path, props

        return None, None

    # offer a stream tube to another room (new API)
    address = t.create_server(q, address_type, block_reading=True)

    request = {
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
        cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
        cs.TARGET_ID: '*****@*****.**',
        cs.STREAM_TUBE_SERVICE: 'newecho',
    }
    _, new_tube_path, new_tube_props = \
        join_muc(q, bus, conn, stream, '*****@*****.**', request)

    e = q.expect('dbus-signal', signal='NewChannels',
                 predicate=new_chan_predicate)

    path, prop = find_stream_tube(e.args[0])
    assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
    assert prop[cs.INITIATOR_ID] == '[email protected]/test'
    assert prop[cs.REQUESTED] == True
    assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
    assert prop[cs.TARGET_ID] == '*****@*****.**'
    assert prop[cs.STREAM_TUBE_SERVICE] == 'newecho'

    # check that the tube channel is in the channels list
    all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels',
        dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True)
    assertContains((path, prop), all_channels)

    tube_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamTube')
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE)

    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED

    # offer the tube
    call_async(q, tube_chan.StreamTube, 'Offer', address_type, address, access_control, {'foo': 'bar'})

    stream_event, _, status_event = q.expect_many(
        EventPattern('stream-presence', to='[email protected]/test', predicate=lambda e: t.presence_contains_tube(e)),
        EventPattern('dbus-return', method='Offer'),
        EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN]))

    tube_self_handle = tube_chan.Properties.Get(cs.CHANNEL_IFACE_GROUP, 'SelfHandle')
    assert conn.inspect_contact_sync(tube_self_handle) == '[email protected]/test'

    presence = stream_event.stanza
    tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]'
        % ns.TUBES, presence)
    assert tubes_nodes is not None
    assert len(tubes_nodes) == 1

    stream_tube_id = 666

    tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0])
    assert tube_nodes is not None
    assert len(tube_nodes) == 1
    for tube in tube_nodes:
        assert tube['type'] == 'stream'
        assert not tube.hasAttribute('initiator')
        assert tube['service'] == 'newecho'
        assert not tube.hasAttribute('stream-id')
        assert not tube.hasAttribute('dbus-name')

        stream_tube_id = int(tube['id'])

    params = {}
    parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube)
    for node in parameter_nodes:
        assert node['name'] not in params
        params[node['name']] = (node['type'], str(node))
    assert params == {'foo': ('str', 'bar')}

    bob_handle = conn.get_contact_handle_sync('[email protected]/bob')

    bytestream = connect_to_tube(stream, q, bytestream_cls, '*****@*****.**', stream_tube_id)

    iq_event, socket_event, conn_event = q.expect_many(
        EventPattern('stream-iq', iq_type='result'),
        EventPattern('socket-connected'),
        EventPattern('dbus-signal', signal='NewRemoteConnection',
            interface=cs.CHANNEL_TYPE_STREAM_TUBE))

    handle, access, conn_id = conn_event.args
    assert handle == bob_handle

    protocol = socket_event.protocol
    # start to read from the transport so we can read the control byte
    protocol.transport.startReading()
    t.check_new_connection_access(q, access_control, access, protocol)

    # handle iq_event
    bytestream.check_si_reply(iq_event.stanza)
    tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza)
    assert len(tube) == 1

    use_tube(q, bytestream, protocol, conn_id)

    tube_chan.Channel.Close()
    q.expect_many(
        EventPattern('dbus-signal', signal='Closed'),
        EventPattern('dbus-signal', signal='ChannelClosed'))

    t.cleanup()
예제 #28
0
def test_role_changes(q, bus, conn, stream):
    # The test user joins a room. Bob is an owner (and moderator); the test
    # user starts out with no affiliation and the rôle of participant.
    MUC = 'aoeu@snth'
    chan, _, immutable_props, disco = join_muc(q,
                                               bus,
                                               conn,
                                               stream,
                                               MUC,
                                               role='participant',
                                               also_capture=[
                                                   EventPattern(
                                                       'stream-iq',
                                                       to=MUC,
                                                       iq_type='get',
                                                       query_ns=ns.DISCO_INFO),
                                               ])
    assertContains(cs.CHANNEL_IFACE_ROOM_CONFIG,
                   immutable_props[cs.INTERFACES])

    handle_disco_info_iq(stream, disco.stanza)
    q.expect('dbus-signal',
             signal='PropertiesChanged',
             args=[
                 cs.CHANNEL_IFACE_ROOM_CONFIG, {
                     'ConfigurationRetrieved': True
                 }, []
             ])

    # If we try to change the configuration, Gabble should say no: it knows
    # we're not allowed to do that.
    call_async(q, chan.RoomConfig1, 'UpdateConfiguration', {})
    q.expect('dbus-error', name=cs.PERMISSION_DENIED)

    config = chan.Properties.GetAll(cs.CHANNEL_IFACE_ROOM_CONFIG)
    assert not config['CanUpdateConfiguration'], config

    # If we acquire affiliation='owner', this should be signalled as our
    # becoming able to modify the channel configuration.
    stream.send(make_muc_presence('owner', 'moderator', MUC, 'test'))
    q.expect('dbus-signal',
             signal='PropertiesChanged',
             args=[
                 cs.CHANNEL_IFACE_ROOM_CONFIG, {
                     'CanUpdateConfiguration': True
                 }, []
             ])

    # Due to silliness, Gabble has to grab 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)

    # Bob's ownership rights being taken away should have no effect.
    stream.send(make_muc_presence('none', 'participant', MUC, 'bob'))

    # So now we're an owner, and CanUpdateConfiguration is True, we should be
    # able to change some configuration.
    props = dbus.Dictionary({
        'Persistent': True,
    }, signature='sv')
    call_async(q, chan.RoomConfig1, 'UpdateConfiguration', props)

    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)

    event = q.expect('stream-iq', to=MUC, iq_type='set', query_ns=ns.MUC_OWNER)
    handle_muc_owner_set_iq(stream, event.stanza,
                            {'muc#roomconfig_persistentroom': ['1']})

    q.expect_many(
        EventPattern('dbus-return', method='UpdateConfiguration'),
        EventPattern(
            'dbus-signal',
            signal='PropertiesChanged',
            args=[cs.CHANNEL_IFACE_ROOM_CONFIG, {
                'Persistent': True
            }, []]))

    # If we lose our affiliation, that should be signalled too.
    stream.send(make_muc_presence('none', 'participant', MUC, 'test'))
    q.expect('dbus-signal',
             signal='PropertiesChanged',
             args=[
                 cs.CHANNEL_IFACE_ROOM_CONFIG, {
                     'CanUpdateConfiguration': False
                 }, []
             ])

    # Gabble should once again reject attempts to change the configuration
    call_async(q, chan.RoomConfig1, 'UpdateConfiguration', {})
    q.expect('dbus-error', name=cs.PERMISSION_DENIED)
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

    conn.Connect()

    _, iq_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"),
    )

    acknowledge_iq(stream, iq_event.stanza)

    self_handle = conn.GetSelfHandle()
    self_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0]

    t.check_conn_properties(q, conn)

    room_handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn, stream, "*****@*****.**")

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

    bob_handle = conn.RequestHandles(cs.HT_CONTACT, ["[email protected]/bob"])[0]

    address = t.create_server(q, address_type)

    # offer stream tube (old API) using an Unix socket
    call_async(
        q,
        tubes_iface,
        "OfferStreamTube",
        "echo",
        sample_parameters,
        address_type,
        address,
        access_control,
        access_control_param,
    )

    new_tube_event, stream_event, _, new_channels_event = q.expect_many(
        EventPattern("dbus-signal", signal="NewTube"),
        EventPattern("stream-presence", to="[email protected]/test"),
        EventPattern("dbus-return", method="OfferStreamTube"),
        EventPattern("dbus-signal", signal="NewChannels"),
    )

    # handle new_tube_event
    stream_tube_id = new_tube_event.args[0]
    assert new_tube_event.args[1] == tubes_self_handle
    assert new_tube_event.args[2] == 1  # Stream
    assert new_tube_event.args[3] == "echo"
    assert new_tube_event.args[4] == sample_parameters
    assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN

    # handle stream_event
    # We announce our newly created tube in our muc presence
    presence = stream_event.stanza
    x_nodes = xpath.queryForNodes('/presence/x[@xmlns="http://jabber.org/' 'protocol/muc"]', presence)
    assert x_nodes is not None
    assert len(x_nodes) == 1

    tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence)
    assert tubes_nodes is not None
    assert len(tubes_nodes) == 1

    tube_nodes = xpath.queryForNodes("/tubes/tube", tubes_nodes[0])
    assert tube_nodes is not None
    assert len(tube_nodes) == 1
    for tube in tube_nodes:
        assert tube["type"] == "stream"
        assert not tube.hasAttribute("initiator")
        assert tube["service"] == "echo"
        assert not tube.hasAttribute("stream-id")
        assert not tube.hasAttribute("dbus-name")
        assert tube["id"] == str(stream_tube_id)

    params = {}
    parameter_nodes = xpath.queryForNodes("/tube/parameters/parameter", tube)
    for node in parameter_nodes:
        assert node["name"] not in params
        params[node["name"]] = (node["type"], str(node))
    assert params == {"ay": ("bytes", "aGVsbG8="), "s": ("str", "hello"), "i": ("int", "-123"), "u": ("uint", "123")}

    # tube is also announced using new API
    channels = new_channels_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] == tubes_self_handle
    assert props[cs.INITIATOR_ID] == "[email protected]/test"
    assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE]
    assert props[cs.REQUESTED] == True
    assert props[cs.TARGET_HANDLE] == room_handle
    assert props[cs.TARGET_ID] == "*****@*****.**"
    assert props[cs.STREAM_TUBE_SERVICE] == "echo"

    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_OPEN

    tubes = tubes_iface.ListTubes(byte_arrays=True)
    assert tubes == [
        (stream_tube_id, tubes_self_handle, 1, "echo", sample_parameters, cs.TUBE_CHANNEL_STATE_OPEN)  # Stream
    ]

    assert len(tubes) == 1, unwrap(tubes)
    expected_tube = (
        stream_tube_id,
        tubes_self_handle,
        cs.TUBE_TYPE_STREAM,
        "echo",
        sample_parameters,
        cs.TUBE_STATE_OPEN,
    )
    t.check_tube_in_tubes(expected_tube, tubes)

    # FIXME: if we use an unknown JID here, everything fails
    # (the code uses lookup where it should use ensure)

    bytestream = connect_to_tube(stream, q, bytestream_cls, "*****@*****.**", stream_tube_id)

    iq_event, socket_event, _, conn_event = q.expect_many(
        EventPattern("stream-iq", iq_type="result"),
        EventPattern("socket-connected"),
        EventPattern(
            "dbus-signal",
            signal="StreamTubeNewConnection",
            args=[stream_tube_id, bob_handle],
            interface=cs.CHANNEL_TYPE_TUBES,
        ),
        EventPattern("dbus-signal", signal="NewRemoteConnection", interface=cs.CHANNEL_TYPE_STREAM_TUBE),
    )

    protocol = socket_event.protocol

    # handle iq_event
    bytestream.check_si_reply(iq_event.stanza)
    tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza)
    assert len(tube) == 1

    handle, access, conn_id = conn_event.args
    assert handle == bob_handle

    use_tube(q, bytestream, protocol, conn_id)

    # offer a stream tube to another room (new API)
    address = t.create_server(q, address_type, block_reading=True)

    request = {
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
        cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
        cs.TARGET_ID: "*****@*****.**",
        cs.STREAM_TUBE_SERVICE: "newecho",
    }
    _, _, new_tube_path, new_tube_props = join_muc(q, bus, conn, stream, "*****@*****.**", request)

    # first text and tubes channels are announced
    event = q.expect("dbus-signal", signal="NewChannels")
    channels = event.args[0]
    assert len(channels) == 2
    path1, prop1 = channels[0]
    path2, prop2 = channels[1]
    assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES]

    got_text, got_tubes = False, False
    for path, props in channels:
        if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT:
            got_text = True
        elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES:
            got_tubes = True
        else:
            assert False

        assert props[cs.INITIATOR_HANDLE] == self_handle
        assert props[cs.INITIATOR_ID] == self_name
        assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES]
        assert props[cs.TARGET_ID] == "*****@*****.**"
        assert props[cs.REQUESTED] == False

    assert (got_text, got_tubes) == (True, True)

    # now the tube channel is announced
    # FIXME: in this case, all channels should probably be announced together
    event = q.expect("dbus-signal", signal="NewChannels")
    channels = event.args[0]
    assert len(channels) == 1
    path, prop = channels[0]
    assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
    assert prop[cs.INITIATOR_ID] == "[email protected]/test"
    assert prop[cs.REQUESTED] == True
    assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
    assert prop[cs.TARGET_ID] == "*****@*****.**"
    assert prop[cs.STREAM_TUBE_SERVICE] == "newecho"

    # check that the tube channel is in the channels list
    all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, "Channels", dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True)
    assertContains((path, prop), all_channels)

    tube_chan = bus.get_object(conn.bus_name, path)
    stream_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
    chan_iface = dbus.Interface(tube_chan, cs.CHANNEL)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE)

    assert tube_props["State"] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED

    # offer the tube
    call_async(q, stream_tube_iface, "Offer", address_type, address, access_control, {"foo": "bar"})

    new_tube_event, stream_event, _, status_event = q.expect_many(
        EventPattern("dbus-signal", signal="NewTube"),
        EventPattern("stream-presence", to="[email protected]/test"),
        EventPattern("dbus-return", method="Offer"),
        EventPattern("dbus-signal", signal="TubeChannelStateChanged", args=[cs.TUBE_CHANNEL_STATE_OPEN]),
    )

    tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP)
    assert conn.InspectHandles(cs.HT_CONTACT, [tube_self_handle]) == ["[email protected]/test"]

    # handle new_tube_event
    stream_tube_id = new_tube_event.args[0]
    assert new_tube_event.args[2] == 1  # Stream
    assert new_tube_event.args[3] == "newecho"
    assert new_tube_event.args[4] == {"foo": "bar"}
    assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN

    presence = stream_event.stanza
    x_nodes = xpath.queryForNodes('/presence/x[@xmlns="http://jabber.org/' 'protocol/muc"]', presence)
    assert x_nodes is not None
    assert len(x_nodes) == 1

    tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence)
    assert tubes_nodes is not None
    assert len(tubes_nodes) == 1

    tube_nodes = xpath.queryForNodes("/tubes/tube", tubes_nodes[0])
    assert tube_nodes is not None
    assert len(tube_nodes) == 1
    for tube in tube_nodes:
        assert tube["type"] == "stream"
        assert not tube.hasAttribute("initiator")
        assert tube["service"] == "newecho"
        assert not tube.hasAttribute("stream-id")
        assert not tube.hasAttribute("dbus-name")
        assert tube["id"] == str(stream_tube_id)

    params = {}
    parameter_nodes = xpath.queryForNodes("/tube/parameters/parameter", tube)
    for node in parameter_nodes:
        assert node["name"] not in params
        params[node["name"]] = (node["type"], str(node))
    assert params == {"foo": ("str", "bar")}

    bob_handle = conn.RequestHandles(cs.HT_CONTACT, ["[email protected]/bob"])[0]

    bytestream = connect_to_tube(stream, q, bytestream_cls, "*****@*****.**", stream_tube_id)

    iq_event, socket_event, conn_event = q.expect_many(
        EventPattern("stream-iq", iq_type="result"),
        EventPattern("socket-connected"),
        EventPattern("dbus-signal", signal="NewRemoteConnection", interface=cs.CHANNEL_TYPE_STREAM_TUBE),
    )

    handle, access, conn_id = conn_event.args
    assert handle == bob_handle

    protocol = socket_event.protocol
    # start to read from the transport so we can read the control byte
    protocol.transport.startReading()
    t.check_new_connection_access(q, access_control, access, protocol)

    # handle iq_event
    bytestream.check_si_reply(iq_event.stanza)
    tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza)
    assert len(tube) == 1

    use_tube(q, bytestream, protocol, conn_id)

    chan_iface.Close()
    q.expect_many(EventPattern("dbus-signal", signal="Closed"), EventPattern("dbus-signal", signal="ChannelClosed"))
예제 #30
0
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 = q.expect('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard')

    acknowledge_iq(stream, iq_event.stanza)

    self_handle = conn.GetSelfHandle()
    self_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0]

    t.check_conn_properties(q, conn)

    room_handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn,
        stream, '*****@*****.**')

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

    bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['[email protected]/bob'])[0]

    address = t.create_server(q, address_type)

    # offer stream tube (old API) using an Unix socket
    call_async(q, tubes_iface, 'OfferStreamTube',
        'echo', sample_parameters, address_type, address,
        access_control, access_control_param)

    new_tube_event, stream_event, _, new_channels_event = q.expect_many(
        EventPattern('dbus-signal', signal='NewTube'),
        EventPattern('stream-presence', to='[email protected]/test'),
        EventPattern('dbus-return', method='OfferStreamTube'),
        EventPattern('dbus-signal', signal='NewChannels'))

    # handle new_tube_event
    stream_tube_id = new_tube_event.args[0]
    assert new_tube_event.args[1] == tubes_self_handle
    assert new_tube_event.args[2] == 1       # Stream
    assert new_tube_event.args[3] == 'echo'
    assert new_tube_event.args[4] == sample_parameters
    assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN

    # handle stream_event
    # We announce our newly created tube in our muc presence
    presence = stream_event.stanza
    tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]'
        % ns.TUBES, presence)
    assert tubes_nodes is not None
    assert len(tubes_nodes) == 1

    tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0])
    assert tube_nodes is not None
    assert len(tube_nodes) == 1
    for tube in tube_nodes:
        assert tube['type'] == 'stream'
        assert not tube.hasAttribute('initiator')
        assert tube['service'] == 'echo'
        assert not tube.hasAttribute('stream-id')
        assert not tube.hasAttribute('dbus-name')
        assert tube['id'] == str(stream_tube_id)

    params = {}
    parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube)
    for node in parameter_nodes:
        assert node['name'] not in params
        params[node['name']] = (node['type'], str(node))
    assert params == {'ay': ('bytes', 'aGVsbG8='),
                      's': ('str', 'hello'),
                      'i': ('int', '-123'),
                      'u': ('uint', '123'),
                     }

    # tube is also announced using new API
    channels = new_channels_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] == tubes_self_handle
    assert props[cs.INITIATOR_ID] == '[email protected]/test'
    assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE]
    assert props[cs.REQUESTED] == True
    assert props[cs.TARGET_HANDLE] == room_handle
    assert props[cs.TARGET_ID] == '*****@*****.**'
    assert props[cs.STREAM_TUBE_SERVICE] == 'echo'

    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_OPEN

    tubes = tubes_iface.ListTubes(byte_arrays=True)
    assert tubes == [(
        stream_tube_id,
        tubes_self_handle,
        1,      # Stream
        'echo',
        sample_parameters,
        cs.TUBE_CHANNEL_STATE_OPEN
        )]

    assert len(tubes) == 1, unwrap(tubes)
    expected_tube = (stream_tube_id, tubes_self_handle, cs.TUBE_TYPE_STREAM,
        'echo', sample_parameters, cs.TUBE_STATE_OPEN)
    t.check_tube_in_tubes(expected_tube, tubes)

    # FIXME: if we use an unknown JID here, everything fails
    # (the code uses lookup where it should use ensure)

    bytestream = connect_to_tube(stream, q, bytestream_cls, '*****@*****.**', stream_tube_id)

    iq_event, socket_event, _, conn_event = q.expect_many(
        EventPattern('stream-iq', iq_type='result'),
        EventPattern('socket-connected'),
        EventPattern('dbus-signal', signal='StreamTubeNewConnection',
            args=[stream_tube_id, bob_handle], interface=cs.CHANNEL_TYPE_TUBES),
        EventPattern('dbus-signal', signal='NewRemoteConnection',
            interface=cs.CHANNEL_TYPE_STREAM_TUBE))

    protocol = socket_event.protocol

    # handle iq_event
    bytestream.check_si_reply(iq_event.stanza)
    tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza)
    assert len(tube) == 1

    handle, access, conn_id = conn_event.args
    assert handle == bob_handle

    use_tube(q, bytestream, protocol, conn_id)

    # offer a stream tube to another room (new API)
    address = t.create_server(q, address_type, block_reading=True)

    request = {
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
        cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
        cs.TARGET_ID: '*****@*****.**',
        cs.STREAM_TUBE_SERVICE: 'newecho',
    }
    _, _, new_tube_path, new_tube_props = \
        join_muc(q, bus, conn, stream, '*****@*****.**', request)

    # The order in which the NewChannels signals are fired is
    # undefined -- it could be the (tubes, text) channels first, or it
    # could be the tube channel first; so let's accept either order
    # here.

    first, second = q.expect_many(
        EventPattern('dbus-signal', signal='NewChannels'),
        EventPattern('dbus-signal', signal='NewChannels'))

    # NewChannels signal with the text and tubes channels together.
    def nc_textandtubes(event):
        channels = event.args[0]
        assert len(channels) == 2
        path1, prop1 = channels[0]
        path2, prop2 = channels[1]
        assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == \
            [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES]

        got_text, got_tubes = False, False
        for path, props in channels:
            if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT:
                got_text = True
            elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES:
                got_tubes = True
            else:
                assert False

            assert props[cs.INITIATOR_HANDLE] == self_handle
            assert props[cs.INITIATOR_ID] == self_name
            assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES]
            assert props[cs.TARGET_ID] == '*****@*****.**'
            assert props[cs.REQUESTED] == False

        assert (got_text, got_tubes) == (True, True)

    # NewChannels signal with the tube channel.
    def nc_tube(event):
        # FIXME: in this case, all channels should probably be announced together
        channels = event.args[0]
        assert len(channels) == 1
        path, prop = channels[0]
        assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
        assert prop[cs.INITIATOR_ID] == '[email protected]/test'
        assert prop[cs.REQUESTED] == True
        assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
        assert prop[cs.TARGET_ID] == '*****@*****.**'
        assert prop[cs.STREAM_TUBE_SERVICE] == 'newecho'

        return path, prop

    if len(first.args[0]) == 1:
        path, prop = nc_tube(first)
        nc_textandtubes(second)
    else:
        nc_textandtubes(first)
        path, prop = nc_tube(second)

    # check that the tube channel is in the channels list
    all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels',
        dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True)
    assertContains((path, prop), all_channels)

    tube_chan = bus.get_object(conn.bus_name, path)
    stream_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
    chan_iface = dbus.Interface(tube_chan, cs.CHANNEL)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE)

    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED

    # offer the tube
    call_async(q, stream_tube_iface, 'Offer', address_type, address, access_control, {'foo': 'bar'})

    new_tube_event, stream_event, _, status_event = q.expect_many(
        EventPattern('dbus-signal', signal='NewTube'),
        EventPattern('stream-presence', to='[email protected]/test'),
        EventPattern('dbus-return', method='Offer'),
        EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN]))

    tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP)
    assert conn.InspectHandles(cs.HT_CONTACT, [tube_self_handle]) == ['[email protected]/test']

    # handle new_tube_event
    stream_tube_id = new_tube_event.args[0]
    assert new_tube_event.args[2] == 1       # Stream
    assert new_tube_event.args[3] == 'newecho'
    assert new_tube_event.args[4] == {'foo': 'bar'}
    assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN

    presence = stream_event.stanza
    tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]'
        % ns.TUBES, presence)
    assert tubes_nodes is not None
    assert len(tubes_nodes) == 1

    tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0])
    assert tube_nodes is not None
    assert len(tube_nodes) == 1
    for tube in tube_nodes:
        assert tube['type'] == 'stream'
        assert not tube.hasAttribute('initiator')
        assert tube['service'] == 'newecho'
        assert not tube.hasAttribute('stream-id')
        assert not tube.hasAttribute('dbus-name')
        assert tube['id'] == str(stream_tube_id)

    params = {}
    parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube)
    for node in parameter_nodes:
        assert node['name'] not in params
        params[node['name']] = (node['type'], str(node))
    assert params == {'foo': ('str', 'bar')}

    bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['[email protected]/bob'])[0]

    bytestream = connect_to_tube(stream, q, bytestream_cls, '*****@*****.**', stream_tube_id)

    iq_event, socket_event, conn_event = q.expect_many(
        EventPattern('stream-iq', iq_type='result'),
        EventPattern('socket-connected'),
        EventPattern('dbus-signal', signal='NewRemoteConnection',
            interface=cs.CHANNEL_TYPE_STREAM_TUBE))

    handle, access, conn_id = conn_event.args
    assert handle == bob_handle

    protocol = socket_event.protocol
    # start to read from the transport so we can read the control byte
    protocol.transport.startReading()
    t.check_new_connection_access(q, access_control, access, protocol)

    # handle iq_event
    bytestream.check_si_reply(iq_event.stanza)
    tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza)
    assert len(tube) == 1

    use_tube(q, bytestream, protocol, conn_id)

    chan_iface.Close()
    q.expect_many(
        EventPattern('dbus-signal', signal='Closed'),
        EventPattern('dbus-signal', signal='ChannelClosed'))
예제 #31
0
def test(q, bus, conn, stream, access_control):
    iq_event = q.expect('stream-iq',
                        to=None,
                        query_ns='vcard-temp',
                        query_name='vCard')

    acknowledge_iq(stream, iq_event.stanza)

    # check if we can request muc D-Bus tube
    t.check_conn_properties(q, conn)

    self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
    self_name = conn.inspect_contact_sync(self_handle)

    # offer a D-Bus tube to another room using new API
    muc = '*****@*****.**'
    request = {
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE,
        cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
        cs.TARGET_ID: '*****@*****.**',
        cs.DBUS_TUBE_SERVICE_NAME: 'com.example.TestCase',
    }
    join_muc(q, bus, conn, stream, muc, request=request)

    exv = q.expect('dbus-signal', signal='NewChannels')

    channels = exv.args[0]
    assert len(channels) == 1
    path, prop = channels[0]
    assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
    assert prop[cs.INITIATOR_ID] == '[email protected]/test'
    assert prop[cs.REQUESTED] == True
    assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM
    assert prop[cs.TARGET_ID] == '*****@*****.**'
    assert prop[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
    assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [
        cs.SOCKET_ACCESS_CONTROL_CREDENTIALS,
        cs.SOCKET_ACCESS_CONTROL_LOCALHOST
    ]

    # check that the tube channel is in the channels list
    all_channels = conn.Get(cs.CONN_IFACE_REQUESTS,
                            'Channels',
                            dbus_interface=cs.PROPERTIES_IFACE,
                            byte_arrays=True)
    assertContains((path, prop), all_channels)

    tube_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'DBusTube')
    tube_props = tube_chan.Properties.GetAll(cs.CHANNEL_IFACE_TUBE,
                                             byte_arrays=True)

    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED

    # try to offer using a wrong access control
    try:
        tube_chan.DBusTube.Offer(sample_parameters,
                                 cs.SOCKET_ACCESS_CONTROL_PORT)
    except dbus.DBusException as e:
        assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
    else:
        assert False

    # offer the tube
    call_async(q, tube_chan.DBusTube, 'Offer', sample_parameters,
               access_control)

    presence_event, return_event, status_event, dbus_changed_event = q.expect_many(
        EventPattern('stream-presence',
                     to='[email protected]/test',
                     predicate=lambda e: t.presence_contains_tube(e)),
        EventPattern('dbus-return', method='Offer'),
        EventPattern('dbus-signal',
                     signal='TubeChannelStateChanged',
                     args=[cs.TUBE_CHANNEL_STATE_OPEN]),
        EventPattern('dbus-signal',
                     signal='DBusNamesChanged',
                     interface=cs.CHANNEL_TYPE_DBUS_TUBE))

    tube_self_handle = tube_chan.Properties.Get(cs.CHANNEL_IFACE_GROUP,
                                                'SelfHandle')
    assert tube_self_handle != 0

    # handle presence_event
    # We announce our newly created tube in our muc presence
    presence = presence_event.stanza
    dbus_stream_id, my_bus_name, dbus_tube_id = check_tube_in_presence(
        presence, '[email protected]/test')

    # handle dbus_changed_event
    added, removed = dbus_changed_event.args
    assert added == {tube_self_handle: my_bus_name}
    assert removed == []

    dbus_tube_adr = return_event.value[0]

    bob_bus_name = ':2.Ym9i'
    bob_handle = conn.get_contact_handle_sync('[email protected]/bob')

    def bob_in_tube():
        presence = elem('presence',
                        from_='[email protected]/bob',
                        to='*****@*****.**')(
                            elem('x', xmlns=ns.MUC_USER),
                            elem('tubes', xmlns=ns.TUBES)(
                                elem('tube',
                                     type='dbus',
                                     initiator='[email protected]/test',
                                     service='com.example.TestCase',
                                     id=str(dbus_tube_id))(elem('parameters')(
                                         elem('parameter',
                                              name='ay',
                                              type='bytes')(u'aGVsbG8='),
                                         elem('parameter',
                                              name='s',
                                              type='str')(u'hello'),
                                         elem('parameter',
                                              name='i',
                                              type='int')(u'-123'),
                                         elem('parameter',
                                              name='u',
                                              type='uint')(u'123')))))

        # have to add stream-id and dbus-name attributes manually as we can't use
        # keyword with '-'...
        tube_node = xpath.queryForNodes('/presence/tubes/tube', presence)[0]
        tube_node['stream-id'] = dbus_stream_id
        tube_node['dbus-name'] = bob_bus_name
        stream.send(presence)

    # Bob joins the tube
    bob_in_tube()

    dbus_changed_event = q.expect('dbus-signal',
                                  signal='DBusNamesChanged',
                                  interface=cs.CHANNEL_TYPE_DBUS_TUBE)

    added, removed = dbus_changed_event.args
    assert added == {bob_handle: bob_bus_name}
    assert removed == []

    tube = Connection(dbus_tube_adr)
    fire_signal_on_tube(q, tube, '*****@*****.**', dbus_stream_id,
                        my_bus_name)

    names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE,
                          'DBusNames',
                          dbus_interface=cs.PROPERTIES_IFACE)
    assert names == {tube_self_handle: my_bus_name, bob_handle: bob_bus_name}

    # Bob leave the tube
    presence = elem('presence',
                    from_='[email protected]/bob',
                    to='*****@*****.**')(elem('x', xmlns=ns.MUC_USER),
                                               elem('tubes', xmlns=ns.TUBES))
    stream.send(presence)

    dbus_changed_event = q.expect('dbus-signal',
                                  signal='DBusNamesChanged',
                                  interface=cs.CHANNEL_TYPE_DBUS_TUBE)

    added, removed = dbus_changed_event.args
    assert added == {}
    assert removed == [bob_handle]

    names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE,
                          'DBusNames',
                          dbus_interface=cs.PROPERTIES_IFACE)
    assert names == {tube_self_handle: my_bus_name}

    tube_chan.Channel.Close()
    _, _, event = q.expect_many(
        EventPattern('dbus-signal', signal='Closed'),
        EventPattern('dbus-signal', signal='ChannelClosed'),
        EventPattern('stream-presence',
                     to='[email protected]/test',
                     presence_type='unavailable'))

    # we must echo the MUC presence so the room will actually close
    # and we should wait to make sure gabble has actually parsed our
    # echo before trying to rejoin
    echo_muc_presence(q, stream, event.stanza, 'none', 'participant')
    sync_stream(q, stream)

    # rejoin the room
    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('stream-presence', to='[email protected]/test')

    # Bob is in the room and in the tube
    bob_in_tube()

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

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

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

    # tube and text is created
    text_event, tube_event = q.expect_many(
        EventPattern('dbus-signal', signal='NewChannels', predicate=new_text),
        EventPattern('dbus-signal', signal='NewChannels', predicate=new_tube))

    channels = exv.args[0]
    tube_path, props = tube_event.args[0][0]
    assertEquals(cs.CHANNEL_TYPE_DBUS_TUBE, props[cs.CHANNEL_TYPE])
    assertEquals('[email protected]/test', props[cs.INITIATOR_ID])
    assertEquals(False, props[cs.REQUESTED])
    assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE])
    assertEquals('com.example.TestCase', props[cs.DBUS_TUBE_SERVICE_NAME])

    _, props = text_event.args[0][0]
    assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE])
    assertEquals(True, props[cs.REQUESTED])

    # tube is local-pending
    tube_chan = bus.get_object(conn.bus_name, tube_path)
    state = tube_chan.Get(cs.CHANNEL_IFACE_TUBE,
                          'State',
                          dbus_interface=dbus.PROPERTIES_IFACE)
    assertEquals(cs.TUBE_STATE_LOCAL_PENDING, state)
예제 #32
0
def test(q, bus, conn, stream):
    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_muc(q, bus, conn, stream, '*****@*****.**')

    # bob offers a stream tube
    stream_tube_id = 1

    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'))
    stream.send(presence)

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

    e = q.expect('dbus-signal',
                 signal='NewChannels',
                 predicate=new_chan_predicate)
    channels = e.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE

    tube_chan = bus.get_object(conn.bus_name, path)
    tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)

    call_async(q, tube_iface, 'Accept', 0, 0, '', byte_arrays=True)

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

    unix_socket_adr = accept_return_event.value[0]

    factory = EventProtocolClientFactory(q)
    reactor.connectUNIX(unix_socket_adr, factory)

    # expect SI request
    e = q.expect('stream-iq',
                 to='[email protected]/bob',
                 query_ns=ns.SI,
                 query_name='si')

    bytestream, profile = create_from_si_offer(stream, q, BytestreamS5BRelay,
                                               e.stanza,
                                               '[email protected]/bob')

    result, si = bytestream.create_si_reply(e.stanza,
                                            'test@localhost/Resource')
    si.addElement((ns.TUBES, 'tube'))
    stream.send(result)

    # wait SOCKS5 init iq
    id, mode, si, hosts = bytestream._expect_socks5_init()
    for jid, host, port in hosts:
        # the proxy is not announced because we are in a muc
        assert jid != 'proxy.localhost'
def test(q, bus, conn, stream):
    expect_and_handle_get_vcard(q, stream)

    jid = u"*****@*****.**"
    alias = u"Horza"
    handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0]

    # We don't have an interesting alias for Horza
    assertEquals({handle: jid}, conn.Aliasing.GetAliases([handle]))

    # Horza sends us a message containing his preferred nickname.
    stream.send(
        elem("message", from_=jid, type="chat")(elem("body")(u"It's a long story."), elem(ns.NICK, "nick")(alias))
    )
    _, mr = q.expect_many(
        EventPattern("dbus-signal", signal="AliasesChanged", args=[[(handle, alias)]]),
        EventPattern("dbus-signal", signal="MessageReceived"),
    )

    channel = wrap_channel(bus.get_object(conn.bus_name, mr.path), "Text")

    # So now we know his alias.
    assertEquals({handle: alias}, conn.Aliasing.GetAliases([handle]))

    # Presumably to avoid non-contacts being able to make Gabble's memory
    # footprint grow forever, Gabble throws the alias away when we close the
    # channel.
    header = mr.args[0][0]
    channel.Text.AcknowledgePendingMessages([header["pending-message-id"]])
    channel.Close()

    # FIXME: Gabble forgets the alias, but it doesn't signal that it has done
    # so; it probably should.
    # q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, jid)]])
    assertEquals({handle: jid}, conn.Aliasing.GetAliases([handle]))

    # Basically the same test, but in a MUC.
    #
    # It's a bit questionable whether this ought to work.
    # <http://xmpp.org/extensions/xep-0172.html#muc> doesn't have anything to
    # say about including <nick/> in messages; it does talk about including
    # <nick> in your MUC presence, which is actually equally sketchy! If I join
    # a muc with the resource '/wjt', and you join with resource '/ohai' but
    # say that your nickname is 'wjt', what on earth is Alice's UI supposed to
    # show when you send a message?
    #
    # But anyway, at the time of writing this "works", so I'm adding a test to
    # make it explicit.  Perhaps in future we might change this test to verify
    # that it doesn't "work".
    room_jid = "*****@*****.**"
    _, muc, _, _ = join_muc(q, bus, conn, stream, room_jid)

    bob_jid = room_jid + "/bob"
    bob_handle = conn.RequestHandles(cs.HT_CONTACT, [bob_jid])[0]

    assertEquals({bob_handle: "bob"}, conn.Aliasing.GetAliases([bob_handle]))

    stream.send(
        elem("message", from_=bob_jid, type="groupchat")(
            elem("body")(u"My religion dies with me."), elem(ns.NICK, "nick")(alias)
        )
    )

    q.expect_many(
        EventPattern("dbus-signal", signal="AliasesChanged", args=[[(bob_handle, alias)]]),
        EventPattern("dbus-signal", signal="MessageReceived"),
    )

    assertEquals({bob_handle: alias}, conn.Aliasing.GetAliases([bob_handle]))

    muc.Close()
    q.expect("stream-presence", to=room_jid + "/test")
    echo = make_muc_presence("member", "none", room_jid, "test")
    echo["type"] = "unavailable"
    stream.send(echo)
    q.expect("dbus-signal", signal="ChannelClosed")

    # FIXME: Gabble forgets the alias, but it doesn't signal that it has done
    # so; it probably should.
    # q.expect('dbus-signal', signal='AliasesChanged',
    #     args=[[(bob_handle, 'bob')]])
    assertEquals({bob_handle: "bob"}, conn.Aliasing.GetAliases([bob_handle]))