Ejemplo n.º 1
0
async def test_export_alias():
  async with MessageBus().connect() as bus:

    interface = ExampleInterface('test.interface')

    export_path = '/test/path'
    export_path2 = '/test/path/child'

    bus.export(export_path, interface)
    bus.export(export_path2, interface)

    result = await bus.call(
        Message(destination=bus.unique_name,
                path=export_path,
                interface='test.interface',
                member='some_method'))
    assert result.message_type is MessageType.METHOD_RETURN, result.body[0]

    assert interface._method_called
    interface._method_called = False

    result = await bus.call(
        Message(destination=bus.unique_name,
                path=export_path2,
                interface='test.interface',
                member='some_method'))
    assert result.message_type is MessageType.METHOD_RETURN, result.body[0]
    assert interface._method_called
Ejemplo n.º 2
0
def test_unmarshalling_with_table():
    for item in table:

        unmarshaller = Unmarshaller()
        unmarshaller.feed(bytes.fromhex(item['data']))
        try:
            unmarshaller.unmarshall()
        except Exception as e:
            print('message failed to unmarshall:')
            print(json_dump(item['message']))
            raise e

        message = Message(**item['message'])

        body = []
        for i, type_ in enumerate(message.signature_tree.types):
            body.append(replace_variants(type_, message.body[i]))
        message.body = body

        for attr in [
                'body', 'signature', 'message_type', 'destination', 'path',
                'interface', 'member', 'flags', 'serial'
        ]:
            assert getattr(unmarshaller.message,
                           attr) == getattr(message,
                                            attr), f'attr doesnt match: {attr}'
Ejemplo n.º 3
0
async def test_sending_messages_between_buses():
    async with MessageBus().connect() as bus1, \
            MessageBus().connect() as bus2:

        msg = Message(destination=bus1.unique_name,
                      path='/org/test/path',
                      interface='org.test.iface',
                      member='SomeMember',
                      serial=bus2.next_serial())

        def message_handler(sent):
            if sent.sender == bus2.unique_name and sent.serial == msg.serial:
                assert sent.path == msg.path
                assert sent.serial == msg.serial
                assert sent.interface == msg.interface
                assert sent.member == msg.member
                bus1.send(Message.new_method_return(sent, 's', ['got it']))
                bus1.remove_message_handler(message_handler)
                return True

        bus1.add_message_handler(message_handler)

        reply = await bus2.call(msg)

        assert reply.message_type == MessageType.METHOD_RETURN
        assert reply.sender == bus1.unique_name
        assert reply.signature == 's'
        assert reply.body == ['got it']
        assert reply.reply_serial == msg.serial

        def message_handler_error(sent):
            if sent.sender == bus2.unique_name and sent.serial == msg.serial:
                assert sent.path == msg.path
                assert sent.serial == msg.serial
                assert sent.interface == msg.interface
                assert sent.member == msg.member
                bus1.send(
                    Message.new_error(sent, 'org.test.Error',
                                      'throwing an error'))
                bus1.remove_message_handler(message_handler_error)
                return True

        bus1.add_message_handler(message_handler_error)

        msg.serial = bus2.next_serial()

        reply = await bus2.call(msg)

        assert reply.message_type == MessageType.ERROR
        assert reply.sender == bus1.unique_name
        assert reply.reply_serial == msg.serial
        assert reply.error_name == 'org.test.Error'
        assert reply.signature == 's'
        assert reply.body == ['throwing an error']

        msg.serial = bus2.next_serial()
        msg.flags = MessageFlag.NO_REPLY_EXPECTED
        reply = await bus2.call(msg)
        assert reply is None
Ejemplo n.º 4
0
def test_ay_buffer():
    body = [bytes(10000)]
    msg = Message(path='/test', member='test', signature='ay', body=body)
    marshalled = msg._marshall()
    unmarshaller = Unmarshaller()
    unmarshaller.feed(marshalled)
    unmarshalled_msg = unmarshaller.unmarshall()
    assert unmarshalled_msg.body[0] == body[0]
Ejemplo n.º 5
0
async def test_object_manager():
    async with MessageBus().connect() as bus1, \
            MessageBus().connect() as bus2:
        expected_reply = {
            '/test/path/deeper': {
                'test.interface2': {
                    'Bar': Variant('s', 'str'),
                    'Foo': Variant('y', 42)
                }
            }
        }
        reply_ext = {
            '/test/path': {
                'test.interface1': {},
                'test.interface2': {
                    'Bar': Variant('s', 'str'),
                    'Foo': Variant('y', 42)
                }
            }
        }

        interface = ExampleInterface('test.interface1')
        interface2 = ExampleComplexInterface('test.interface2')

        export_path = '/test/path'
        bus1.export(export_path, interface)
        bus1.export(export_path, interface2)
        bus1.export(export_path + '/deeper', interface2)

        reply_root = await bus2.call(
            Message(destination=bus1.unique_name,
                    path='/',
                    interface='org.freedesktop.DBus.ObjectManager',
                    member='GetManagedObjects'))

        reply_level1 = await bus2.call(
            Message(destination=bus1.unique_name,
                    path=export_path,
                    interface='org.freedesktop.DBus.ObjectManager',
                    member='GetManagedObjects'))

        reply_level2 = await bus2.call(
            Message(destination=bus1.unique_name,
                    path=export_path + '/deeper',
                    interface='org.freedesktop.DBus.ObjectManager',
                    member='GetManagedObjects'))

        assert reply_root.signature == 'a{oa{sa{sv}}}'
        assert reply_level1.signature == 'a{oa{sa{sv}}}'
        assert reply_level2.signature == 'a{oa{sa{sv}}}'

        assert reply_level2.body == [{}]
        assert reply_level1.body == [expected_reply]
        expected_reply.update(reply_ext)
        assert reply_root.body == [expected_reply]
Ejemplo n.º 6
0
async def test_standard_interface_properties():
    # standard interfaces have no properties, but should still behave correctly
    # when you try to call the methods anyway (#49)
    async with MessageBus().connect() as bus1, \
            MessageBus().connect() as bus2:

        interface = ExampleInterface('test.interface1')
        export_path = '/test/path'
        bus1.export(export_path, interface)

        for iface in [
                'org.freedesktop.DBus.Properties',
                'org.freedesktop.DBus.Introspectable',
                'org.freedesktop.DBus.Peer',
                'org.freedesktop.DBus.ObjectManager'
        ]:

            result = await bus2.call(
                Message(destination=bus1.unique_name,
                        path=export_path,
                        interface='org.freedesktop.DBus.Properties',
                        member='Get',
                        signature='ss',
                        body=[iface, 'anything']))
            assert result.message_type is MessageType.ERROR
            assert result.error_name == ErrorType.UNKNOWN_PROPERTY.value

            result = await bus2.call(
                Message(destination=bus1.unique_name,
                        path=export_path,
                        interface='org.freedesktop.DBus.Properties',
                        member='Set',
                        signature='ssv',
                        body=[iface, 'anything',
                              Variant('s', 'new thing')]))
            assert result.message_type is MessageType.ERROR
            assert result.error_name == ErrorType.UNKNOWN_PROPERTY.value

            result = await bus2.call(
                Message(destination=bus1.unique_name,
                        path=export_path,
                        interface='org.freedesktop.DBus.Properties',
                        member='GetAll',
                        signature='s',
                        body=[iface]))
            assert result.message_type is MessageType.METHOD_RETURN
            assert result.body == [{}]
Ejemplo n.º 7
0
 async def call_properties(member, signature, body):
     return await bus2.call(
         Message(destination=bus1.unique_name,
                 path=export_path,
                 interface='org.freedesktop.DBus.Properties',
                 member=member,
                 signature=signature,
                 body=body))
Ejemplo n.º 8
0
async def test_standard_interfaces():
    async with MessageBus().connect() as bus:
        msg = Message(destination='org.freedesktop.DBus',
                      path='/org/freedesktop/DBus',
                      interface='org.freedesktop.DBus',
                      member='ListNames',
                      serial=bus.next_serial())
        reply = await bus.call(msg)

        assert reply.message_type == MessageType.METHOD_RETURN
        assert reply.reply_serial == msg.serial
        assert reply.signature == 'as'
        assert bus.unique_name in reply.body[0]

        msg.interface = 'org.freedesktop.DBus.Introspectable'
        msg.member = 'Introspect'
        msg.serial = bus.next_serial()

        reply = await bus.call(msg)
        assert reply.message_type == MessageType.METHOD_RETURN
        assert reply.reply_serial == msg.serial
        assert reply.signature == 's'
        assert type(reply.body[0]) is str

        msg.member = 'MemberDoesNotExist'
        msg.serial = bus.next_serial()

        reply = await bus.call(msg)
        assert reply.message_type == MessageType.ERROR
        assert reply.reply_serial == msg.serial
        assert reply.error_name
        assert reply.signature == 's'
        assert type(reply.body[0]) is str
Ejemplo n.º 9
0
 def message_handler_error(sent):
     if sent.sender == bus2.unique_name and sent.serial == msg.serial:
         assert sent.path == msg.path
         assert sent.serial == msg.serial
         assert sent.interface == msg.interface
         assert sent.member == msg.member
         bus1.send(Message.new_error(sent, 'org.test.Error', 'throwing an error'))
         bus1.remove_message_handler(message_handler_error)
         return True
Ejemplo n.º 10
0
 def message_handler(sent):
     if sent.sender == bus2.unique_name and sent.serial == msg.serial:
         assert sent.path == msg.path
         assert sent.serial == msg.serial
         assert sent.interface == msg.interface
         assert sent.member == msg.member
         bus1.send(Message.new_method_return(sent, 's', ['got it']))
         bus1.remove_message_handler(message_handler)
         return True
Ejemplo n.º 11
0
 async def call(member, signature='', body=[], flags=MessageFlag.NONE):
     return await bus2.call(
         Message(destination=bus1.unique_name,
                 path=export_path,
                 interface=interface.name,
                 member=member,
                 signature=signature,
                 body=body,
                 flags=flags))
Ejemplo n.º 12
0
async def test_property_changed_signal():
    async with MessageBus().connect() as bus1, \
            MessageBus().connect() as bus2:

        await bus2.call(
            Message(destination='org.freedesktop.DBus',
                    path='/org/freedesktop/DBus',
                    interface='org.freedesktop.DBus',
                    member='AddMatch',
                    signature='s',
                    body=[f'sender={bus1.unique_name}']))

        interface = ExampleInterface('test.interface')
        export_path = '/test/path'
        bus1.export(export_path, interface)

        async def wait_for_message():
            # TODO timeout
            future = ValueEvent()

            def message_handler(signal):
                if signal.interface == 'org.freedesktop.DBus.Properties':
                    bus2.remove_message_handler(message_handler)
                    future.set(signal)

            bus2.add_message_handler(message_handler)
            return await future

        bus2.send(
            Message(destination=bus1.unique_name,
                    interface=interface.name,
                    path=export_path,
                    member='do_emit_properties_changed'))

        signal = await wait_for_message()
        assert signal.interface == 'org.freedesktop.DBus.Properties'
        assert signal.member == 'PropertiesChanged'
        assert signal.signature == 'sa{sv}as'
        assert signal.body == [
            interface.name, {
                'string_prop': Variant('s', 'asdf')
            }, ['container_prop']
        ]
Ejemplo n.º 13
0
    async def get_name_owner(name):
        reply = await bus1.call(
            Message(destination='org.freedesktop.DBus',
                    path='/org/freedesktop/DBus',
                    interface='org.freedesktop.DBus',
                    member='GetNameOwner',
                    signature='s',
                    body=[name]))

        assert reply.message_type == MessageType.METHOD_RETURN
        return reply.body[0]
Ejemplo n.º 14
0
def test_sending_signals_between_buses():
    bus1 = MessageBus().connect_sync()
    bus2 = MessageBus().connect_sync()

    add_match_msg = Message(destination='org.freedesktop.DBus',
                            path='/org/freedesktop/DBus',
                            interface='org.freedesktop.DBus',
                            member='AddMatch',
                            signature='s',
                            body=[f'sender={bus2.unique_name}'])

    bus1.call_sync(add_match_msg)

    main = GLib.MainLoop()

    def wait_for_message():
        ret = None

        def message_handler(signal):
            nonlocal ret
            if signal.sender == bus2.unique_name:
                ret = signal
                bus1.remove_message_handler(message_handler)
                main.quit()

        bus1.add_message_handler(message_handler)
        main.run()
        return ret

    bus2.send(
        Message.new_signal('/org/test/path', 'org.test.interface', 'SomeSignal', 's', ['a signal']))

    signal = wait_for_message()

    assert signal.message_type == MessageType.SIGNAL
    assert signal.path == '/org/test/path'
    assert signal.interface == 'org.test.interface'
    assert signal.member == 'SomeSignal'
    assert signal.signature == 's'
    assert signal.body == ['a signal']
Ejemplo n.º 15
0
async def test_peer_interface():
    async with MessageBus().connect() as bus1, \
            MessageBus().connect() as bus2:

        reply = await bus2.call(
            Message(destination=bus1.unique_name,
                    path='/path/doesnt/exist',
                    interface='org.freedesktop.DBus.Peer',
                    member='Ping'))

        assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0]
        assert reply.signature == ''

        reply = await bus2.call(
            Message(destination=bus1.unique_name,
                    path='/path/doesnt/exist',
                    interface='org.freedesktop.DBus.Peer',
                    member='GetMachineId',
                    signature=''))

        assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0]
        assert reply.signature == 's'
Ejemplo n.º 16
0
 def message_handler(sent):
     nonlocal fd_after
     if sent.sender == bus2.unique_name and sent.serial == msg.serial:
         assert sent.path == msg.path
         assert sent.serial == msg.serial
         assert sent.interface == msg.interface
         assert sent.member == msg.member
         assert sent.body == [0]
         assert len(sent.unix_fds) == 1
         fd_after = sent.unix_fds[0]
         bus1.send(Message.new_method_return(sent, 's', ['got it']))
         bus1.remove_message_handler(message_handler)
         return True
Ejemplo n.º 17
0
 async def call(member,
                signature='',
                body=[],
                unix_fds=[],
                iface=interface.name):
     return await bus2.call(
         Message(destination=bus1.unique_name,
                 path=export_path,
                 interface=iface,
                 member=member,
                 signature=signature,
                 body=body,
                 unix_fds=unix_fds))
Ejemplo n.º 18
0
async def test_signals():
  async with MessageBus().connect() as bus1, \
          MessageBus().connect() as bus2:

    interface = ExampleInterface('test.interface')
    export_path = '/test/path'
    bus1.export(export_path, interface)

    await bus2.call(
        Message(destination='org.freedesktop.DBus',
                path='/org/freedesktop/DBus',
                interface='org.freedesktop.DBus',
                member='AddMatch',
                signature='s',
                body=[f'sender={bus1.unique_name}']))

    async with ExpectMessage(bus1, bus2, interface.name) as expected_signal:
        interface.signal_empty()
        assert_signal_ok(signal=await expected_signal,
                         export_path=export_path,
                         member='signal_empty',
                         signature='',
                         body=[])

    async with ExpectMessage(bus1, bus2, interface.name) as expected_signal:
        interface.original_name()
        assert_signal_ok(signal=await expected_signal,
                         export_path=export_path,
                         member='renamed',
                         signature='',
                         body=[])

    async with ExpectMessage(bus1, bus2, interface.name) as expected_signal:
        interface.signal_simple()
        assert_signal_ok(signal=await expected_signal,
                         export_path=export_path,
                         member='signal_simple',
                         signature='s',
                         body=['hello'])

    async with ExpectMessage(bus1, bus2, interface.name) as expected_signal:
        interface.signal_multiple()
        assert_signal_ok(signal=await expected_signal,
                         export_path=export_path,
                         member='signal_multiple',
                         signature='ss',
                         body=['hello', 'world'])

    with pytest.raises(SignalDisabledError):
        interface.signal_disabled()
Ejemplo n.º 19
0
def test_marshalling_with_table():
    for item in table:
        message = Message(**item['message'])

        body = []
        for i, type_ in enumerate(message.signature_tree.types):
            body.append(replace_variants(type_, message.body[i]))
        message.body = body

        buf = message._marshall()
        data = bytes.fromhex(item['data'])

        if buf != data:
            print('message:')
            print(json_dump(item['message']))
            print('')
            print('mine:')
            print_buf(bytes(buf))
            print('')
            print('theirs:')
            print_buf(data)

        assert buf == data
Ejemplo n.º 20
0
async def test_introspectable_interface():
    async with MessageBus().connect() as bus1, \
            MessageBus().connect() as bus2:

        interface = ExampleInterface('test.interface')
        interface2 = ExampleInterface('test.interface2')

        export_path = '/test/path'
        bus1.export(export_path, interface)
        bus1.export(export_path, interface2)

        reply = await bus2.call(
            Message(destination=bus1.unique_name,
                    path=export_path,
                    interface='org.freedesktop.DBus.Introspectable',
                    member='Introspect'))

        assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0]
        assert reply.signature == 's'
        node = intr.Node.parse(reply.body[0])
        assert len(node.interfaces) == standard_interfaces_count + 2
        assert node.interfaces[-1].name == 'test.interface2'
        assert node.interfaces[-2].name == 'test.interface'
        assert not node.nodes

        # introspect works on every path
        reply = await bus2.call(
            Message(destination=bus1.unique_name,
                    path='/path/doesnt/exist',
                    interface='org.freedesktop.DBus.Introspectable',
                    member='Introspect'))
        assert reply.message_type == MessageType.METHOD_RETURN, reply.body[0]
        assert reply.signature == 's'
        node = intr.Node.parse(reply.body[0])
        assert not node.interfaces
        assert not node.nodes
Ejemplo n.º 21
0
async def test_sending_signals_between_buses():
    async with MessageBus().connect() as bus1, \
            MessageBus().connect() as bus2:

        add_match_msg = Message(destination='org.freedesktop.DBus',
                                path='/org/freedesktop/DBus',
                                interface='org.freedesktop.DBus',
                                member='AddMatch',
                                signature='s',
                                body=[f'sender={bus2.unique_name}'])

        await bus1.call(add_match_msg)

        async def wait_for_message():
            future = ValueEvent()

            def message_handler(signal):
                if signal.sender == bus2.unique_name:
                    bus1.remove_message_handler(message_handler)
                    future.set_result(signal)

            bus1.add_message_handler(message_handler)
            return await future

        bus2.send(
            Message.new_signal('/org/test/path', 'org.test.interface',
                               'SomeSignal', 's', ['a signal']))

        signal = await wait_for_message()

        assert signal.message_type == MessageType.SIGNAL
        assert signal.path == '/org/test/path'
        assert signal.interface == 'org.test.interface'
        assert signal.member == 'SomeSignal'
        assert signal.signature == 's'
        assert signal.body == ['a signal']
Ejemplo n.º 22
0
def test_glib_big_message():
    'this tests that nonblocking reads and writes actually work for glib'
    bus1 = glib.MessageBus().connect_sync()
    bus2 = glib.MessageBus().connect_sync()
    interface = ExampleInterface()
    bus1.export('/test/path', interface)

    # two megabytes
    big_body = [bytes(1000000) * 2]
    result = bus2.call_sync(
        Message(destination=bus1.unique_name,
                path='/test/path',
                interface=interface.name,
                member='echo_bytes',
                signature='ay',
                body=big_body))
    assert result.message_type == MessageType.METHOD_RETURN, result.body[0]
    assert result.body[0] == big_body[0]
Ejemplo n.º 23
0
async def test_unexpected_disconnect():
    bus = MessageBus()
    assert not bus.connected
    with pytest.raises((anyio.BrokenResourceError, OSError, anyio.ExceptionGroup)):
        async with bus.connect():
            assert bus.connected

            ping = bus.call(
                Message(destination='org.freedesktop.DBus',
                        path='/org/freedesktop/DBus',
                        interface='org.freedesktop.DBus',
                        member='Ping'))

            os.close(bus._fd)

            # The actual async call will ecancel this scope
            # and re-raise the error when leaving the context
            await ping
Ejemplo n.º 24
0
async def test_sending_file_descriptor_low_level():
    async with MessageBus(negotiate_unix_fd=True).connect() as bus1, \
            MessageBus(negotiate_unix_fd=True).connect() as bus2:

        fd_before = open_file()
        fd_after = None

        msg = Message(destination=bus1.unique_name,
                      path='/org/test/path',
                      interface='org.test.iface',
                      member='SomeMember',
                      body=[0],
                      signature='h',
                      unix_fds=[fd_before])

        def message_handler(sent):
            nonlocal fd_after
            if sent.sender == bus2.unique_name and sent.serial == msg.serial:
                assert sent.path == msg.path
                assert sent.serial == msg.serial
                assert sent.interface == msg.interface
                assert sent.member == msg.member
                assert sent.body == [0]
                assert len(sent.unix_fds) == 1
                fd_after = sent.unix_fds[0]
                bus1.send(Message.new_method_return(sent, 's', ['got it']))
                bus1.remove_message_handler(message_handler)
                return True

        bus1.add_message_handler(message_handler)

        reply = await bus2.call(msg)
        assert reply.body == ['got it']
        assert fd_after is not None

        assert_fds_equal(fd_before, fd_after)

        for fd in [fd_before, fd_after]:
            os.close(fd)
        for bus in [bus1, bus2]:
            bus.disconnect()
Ejemplo n.º 25
0
async def test_interface_add_remove_signal():
  async with MessageBus().connect() as bus1, \
          MessageBus().connect() as bus2:

    await bus2.call(
        Message(destination='org.freedesktop.DBus',
                path='/org/freedesktop/DBus',
                interface='org.freedesktop.DBus',
                member='AddMatch',
                signature='s',
                body=[f'sender={bus1.unique_name}']))

    first_interface = ExampleInterface('test.interface.first')
    second_interface = SecondExampleInterface('test.interface.second')
    export_path = '/test/path'

    # add first interface
    async with ExpectMessage(bus1, bus2, 'org.freedesktop.DBus.ObjectManager') as expected_signal:
        bus1.export(export_path, first_interface)
        assert_signal_ok(
            signal=await expected_signal,
            export_path=export_path,
            member='InterfacesAdded',
            signature='oa{sa{sv}}',
            body=[export_path, {
                'test.interface.first': {
                    'test_prop': Variant('i', 42)
                }
            }])

    # add second interface
    async with ExpectMessage(bus1, bus2, 'org.freedesktop.DBus.ObjectManager') as expected_signal:
        bus1.export(export_path, second_interface)
        assert_signal_ok(signal=await expected_signal,
                         export_path=export_path,
                         member='InterfacesAdded',
                         signature='oa{sa{sv}}',
                         body=[
                             export_path, {
                                 'test.interface.second': {
                                     'str_prop': Variant('s', "abc"),
                                     'list_prop': Variant('ai', [1, 2, 3])
                                 }
                             }
                         ])

    # remove single interface
    async with ExpectMessage(bus1, bus2, 'org.freedesktop.DBus.ObjectManager') as expected_signal:
        bus1.unexport(export_path, second_interface)
        assert_signal_ok(signal=await expected_signal,
                         export_path=export_path,
                         member='InterfacesRemoved',
                         signature='oas',
                         body=[export_path, ['test.interface.second']])

    # add second interface again
    async with ExpectMessage(bus1, bus2, 'org.freedesktop.DBus.ObjectManager') as expected_signal:
        bus1.export(export_path, second_interface)
        await expected_signal

    # remove multiple interfaces
    async with ExpectMessage(bus1, bus2, 'org.freedesktop.DBus.ObjectManager') as expected_signal:
        bus1.unexport(export_path)
        assert_signal_ok(signal=await expected_signal,
                         export_path=export_path,
                         member='InterfacesRemoved',
                         signature='oas',
                         body=[export_path, ['test.interface.first', 'test.interface.second']])
Ejemplo n.º 26
0
 async def ping():
     await bus2.call(
         Message(destination=bus1.unique_name,
                 interface='org.freedesktop.DBus.Peer',
                 path='/test/path',
                 member='Ping'))
Ejemplo n.º 27
0
async def test_tcp_connection_with_forwarding():
    async with anyio.create_task_group() as tg:
        closables = []
        host = '127.0.0.1'
        port = '55556'

        addr_info = parse_address(os.environ.get('DBUS_SESSION_BUS_ADDRESS'))
        assert addr_info
        assert 'abstract' in addr_info[0][1]
        path = f'\0{addr_info[0][1]["abstract"]}'

        async def handle_connection(tcp_sock):
            async with await anyio.connect_unix(path) as unix_sock:
                async with anyio.create_task_group() as tg:

                    async def handle_read():
                        try:
                            while True:
                                data = await tcp_sock.receive()
                                await unix_sock.send(data)
                        except anyio.ClosedResourceError:
                            return

                    async def handle_write():
                        try:
                            while True:
                                data = await unix_sock.receive()
                                await tcp_sock.send(data)
                        except anyio.ClosedResourceError:
                            return

                    tg.spawn(handle_read)
                    tg.spawn(handle_write)

        listener = await anyio.create_tcp_listener(local_port=port,
                                                   local_host=host)
        tg.spawn(listener.serve, handle_connection)
        await anyio.sleep(0.1)

        try:
            async with MessageBus(bus_address=f'tcp:host={host},port={port}'
                                  ).connect() as bus:

                # basic tests to see if it works
                result = await bus.call(
                    Message(destination='org.freedesktop.DBus',
                            path='/org/freedesktop/DBus',
                            interface='org.freedesktop.DBus.Peer',
                            member='Ping'))
                assert result

                intr = await bus.introspect('org.freedesktop.DBus',
                                            '/org/freedesktop/DBus')
                obj = bus.get_proxy_object('org.freedesktop.DBus',
                                           '/org/freedesktop/DBus', intr)
                iface = obj.get_interface('org.freedesktop.DBus.Peer')
                await iface.call_ping()

                sock = bus._sock.extra(anyio.abc.SocketAttribute.raw_socket) \
                        if hasattr(bus._sock,'extra') else bus._sock
                assert sock.getpeername()[0] == host
                assert sock.getsockname()[0] == host
                assert sock.gettimeout() == 0

                pass  # A
        finally:
            tg.cancel_scope.cancel()
Ejemplo n.º 28
0
async def test_high_level_service_fd_passing():
    async with MessageBus(negotiate_unix_fd=True).connect() as bus1, \
            MessageBus(negotiate_unix_fd=True).connect() as bus2:

        interface_name = 'test.interface'
        interface = ExampleInterface(interface_name)
        export_path = '/test/path'

        async def call(member,
                       signature='',
                       body=[],
                       unix_fds=[],
                       iface=interface.name):
            return await bus2.call(
                Message(destination=bus1.unique_name,
                        path=export_path,
                        interface=iface,
                        member=member,
                        signature=signature,
                        body=body,
                        unix_fds=unix_fds))

        bus1.export(export_path, interface)

        # test that an fd can be returned by the service
        reply = await call('ReturnsFd')
        assert reply.message_type == MessageType.METHOD_RETURN, reply.body
        assert reply.signature == 'h'
        assert len(reply.unix_fds) == 1
        assert_fds_equal(interface.get_last_fd(), reply.unix_fds[0])
        interface.cleanup()
        os.close(reply.unix_fds[0])

        # test that an fd can be sent to the service
        fd = open_file()
        reply = await call('AcceptsFd', signature='h', body=[0], unix_fds=[fd])
        assert reply.message_type == MessageType.METHOD_RETURN, reply.body
        assert_fds_equal(interface.get_last_fd(), fd)

        interface.cleanup()
        os.close(fd)

        # signals
        fut = ValueEvent()

        def fd_listener(msg):
            if msg.sender == bus1.unique_name and msg.message_type == MessageType.SIGNAL:
                fut.set_result(msg)

        reply = await bus2.call(
            Message(destination='org.freedesktop.DBus',
                    path='/org/freedesktop/DBus',
                    member='AddMatch',
                    signature='s',
                    body=[f"sender='{bus1.unique_name}'"]))
        assert reply.message_type == MessageType.METHOD_RETURN

        bus2.add_message_handler(fd_listener)
        interface.SignalFd()
        reply = await fut

        assert len(reply.unix_fds) == 1, (reply.unix_fds,
                                          interface.get_last_fd())
        assert reply.body == [0]
        assert_fds_equal(reply.unix_fds[0], interface.get_last_fd())

        interface.cleanup()
        os.close(reply.unix_fds[0])

        # properties
        reply = await call('Get',
                           'ss', [interface_name, 'PropFd'],
                           iface='org.freedesktop.DBus.Properties')
        assert reply.message_type == MessageType.METHOD_RETURN, reply.body
        assert reply.body[0].signature == 'h'
        assert reply.body[0].value == 0
        assert len(reply.unix_fds) == 1
        assert_fds_equal(interface.get_last_fd(), reply.unix_fds[0])
        interface.cleanup()
        os.close(reply.unix_fds[0])

        fd = open_file()
        reply = await call('Set',
                           'ssv', [interface_name, 'PropFd',
                                   Variant('h', 0)],
                           iface='org.freedesktop.DBus.Properties',
                           unix_fds=[fd])
        assert reply.message_type == MessageType.METHOD_RETURN, reply.body
        assert_fds_equal(interface.get_last_fd(), fd)
        interface.cleanup()
        os.close(fd)

        reply = await call('GetAll',
                           's', [interface_name],
                           iface='org.freedesktop.DBus.Properties')
        assert reply.message_type == MessageType.METHOD_RETURN, reply.body
        assert reply.body[0]['PropFd'].signature == 'h'
        assert reply.body[0]['PropFd'].value == 0
        assert len(reply.unix_fds) == 1
        assert_fds_equal(interface.get_last_fd(), reply.unix_fds[0])
        interface.cleanup()
        os.close(reply.unix_fds[0])

        for bus in [bus1, bus2]:
            bus.disconnect()