Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a67f2a71 authored by John Lai's avatar John Lai Committed by Automerger Merge Worker
Browse files

Merge "Floss: Do not handle pairing events when OnPairing" into main am: 3be427b8

parents c42c81c3 3be427b8
Loading
Loading
Loading
Loading
+61 −28
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ from google.protobuf import empty_pb2
import grpc
import grpc
from pandora import host_grpc_aio
from pandora import host_grpc_aio
from pandora import host_pb2
from pandora import host_pb2
from pandora import security_grpc_aio




class HostService(host_grpc_aio.HostServicer):
class HostService(host_grpc_aio.HostServicer):
@@ -41,9 +42,11 @@ class HostService(host_grpc_aio.HostServicer):
    /pandora/bt-test-interfaces/pandora/host.proto
    /pandora/bt-test-interfaces/pandora/host.proto
    """
    """


    def __init__(self, server: grpc.aio.Server, bluetooth: bluetooth_module.Bluetooth):
    def __init__(self, server: grpc.aio.Server, bluetooth: bluetooth_module.Bluetooth,
                 security: security_grpc_aio.SecurityServicer):
        self.server = server
        self.server = server
        self.bluetooth = bluetooth
        self.bluetooth = bluetooth
        self.security = security
        self.waited_connections = set()
        self.waited_connections = set()


    async def FactoryReset(self, request: empty_pb2.Empty, context: grpc.ServicerContext) -> empty_pb2.Empty:
    async def FactoryReset(self, request: empty_pb2.Empty, context: grpc.ServicerContext) -> empty_pb2.Empty:
@@ -64,20 +67,38 @@ class HostService(host_grpc_aio.HostServicer):
    async def Connect(self, request: host_pb2.ConnectRequest,
    async def Connect(self, request: host_pb2.ConnectRequest,
                      context: grpc.ServicerContext) -> host_pb2.ConnectResponse:
                      context: grpc.ServicerContext) -> host_pb2.ConnectResponse:


        class PairingObserver(adapter_client.BluetoothCallbacks, adapter_client.BluetoothConnectionCallbacks):
        class ConnectionObserver(adapter_client.BluetoothConnectionCallbacks):
            """Observer to observe the bond state and the connection state."""
            """Observer to observe the connection state."""


            def __init__(self, client: adapter_client, task):
            def __init__(self, client: adapter_client, task):
                self.client = client
                self.client = client
                self.task = task
                self.task = task


            @utils.glib_callback()
            def on_device_connected(self, remote_device):
                address, _ = remote_device
                if address != self.task['address']:
                    return

                if self.client.is_bonded(address):
                    future = self.task['connect_device']
                    future.get_loop().call_soon_threadsafe(future.set_result, (True, None))

        class PairingObserver(adapter_client.BluetoothCallbacks):
            """Observer to observe the bond state."""

            def __init__(self, client: adapter_client, security: security_grpc_aio.SecurityServicer, task):
                self.client = client
                self.security = security
                self.task = task

            @utils.glib_callback()
            @utils.glib_callback()
            def on_bond_state_changed(self, status, address, state):
            def on_bond_state_changed(self, status, address, state):
                if address != self.task['address']:
                if address != self.task['address']:
                    return
                    return


                if status != 0:
                if status != 0:
                    future = self.task['connect_device']
                    future = self.task['create_bond']
                    future.get_loop().call_soon_threadsafe(
                    future.get_loop().call_soon_threadsafe(
                        future.set_result, (False, f'{address} failed to bond. Status: {status}, State: {state}'))
                        future.set_result, (False, f'{address} failed to bond. Status: {status}, State: {state}'))
                    return
                    return
@@ -86,16 +107,19 @@ class HostService(host_grpc_aio.HostServicer):
                    if not self.client.is_connected(self.task['address']):
                    if not self.client.is_connected(self.task['address']):
                        logging.info('%s calling connect_all_enabled_profiles', address)
                        logging.info('%s calling connect_all_enabled_profiles', address)
                        if not self.client.connect_all_enabled_profiles(self.task['address']):
                        if not self.client.connect_all_enabled_profiles(self.task['address']):
                            future = self.task['connect_device']
                            future = self.task['create_bond']
                            future.get_loop().call_soon_threadsafe(
                            future.get_loop().call_soon_threadsafe(
                                future.set_result,
                                future.set_result,
                                (False, f'{self.task["address"]} failed on connect_all_enabled_profiles'))
                                (False, f'{self.task["address"]} failed on connect_all_enabled_profiles'))
                    else:
                    else:
                        future = self.task['connect_device']
                        future = self.task['create_bond']
                        future.get_loop().call_soon_threadsafe(future.set_result, (True, None))
                        future.get_loop().call_soon_threadsafe(future.set_result, (True, None))


            @utils.glib_callback()
            @utils.glib_callback()
            def on_ssp_request(self, remote_device, class_of_device, variant, passkey):
            def on_ssp_request(self, remote_device, class_of_device, variant, passkey):
                if self.security.manually_confirm:
                    return

                address, _ = remote_device
                address, _ = remote_device
                if address != self.task['address']:
                if address != self.task['address']:
                    return
                    return
@@ -108,39 +132,48 @@ class HostService(host_grpc_aio.HostServicer):
            @utils.glib_callback()
            @utils.glib_callback()
            def on_set_pairing_confirmation(self, err, result):
            def on_set_pairing_confirmation(self, err, result):
                if err or not result:
                if err or not result:
                    future = self.task['connect_device']
                    future = self.task['create_bond']
                    future.get_loop().call_soon_threadsafe(
                    future.get_loop().call_soon_threadsafe(
                        future.set_result, (False, f'Pairing confirmation failed: err: {err}, result: {result}'))
                        future.set_result, (False, f'Pairing confirmation failed: err: {err}, result: {result}'))


            @utils.glib_callback()
            def on_device_connected(self, remote_device):
                address, _ = remote_device
                if address != self.task['address']:
                    return

                if self.client.is_bonded(address):
                    future = self.task['connect_device']
                    future.get_loop().call_soon_threadsafe(future.set_result, (True, None))

        address = utils.address_from(request.address)
        address = utils.address_from(request.address)


        if not self.bluetooth.is_connected(address):
        if not self.bluetooth.is_connected(address):
            name = None
            observer = None
            try:
            try:
                if self.bluetooth.is_bonded(address):
                    connect_device = asyncio.get_running_loop().create_future()
                    connect_device = asyncio.get_running_loop().create_future()
                observer = PairingObserver(self.bluetooth.adapter_client, {
                    observer = ConnectionObserver(self.bluetooth.adapter_client, {
                        'connect_device': connect_device,
                        'connect_device': connect_device,
                        'address': address
                        'address': address
                    })
                    })
                    name = utils.create_observer_name(observer)
                    name = utils.create_observer_name(observer)
                    self.bluetooth.adapter_client.register_callback_observer(name, observer)
                    self.bluetooth.adapter_client.register_callback_observer(name, observer)


                if self.bluetooth.is_bonded(address):
                    self.bluetooth.connect_device(address)
                    self.bluetooth.connect_device(address)
                    success, reason = await connect_device

                    if not success:
                        raise RuntimeError(f'Failed to connect to the {address}. Reason: {reason}')
                else:
                else:
                    create_bond = asyncio.get_running_loop().create_future()
                    observer = PairingObserver(
                        self.bluetooth.adapter_client,
                        self.security,
                        {
                            'create_bond': create_bond,
                            'address': address
                        },
                    )
                    name = utils.create_observer_name(observer)
                    self.bluetooth.adapter_client.register_callback_observer(name, observer)

                    if not self.bluetooth.create_bond(address, floss_enums.BtTransport.BR_EDR):
                    if not self.bluetooth.create_bond(address, floss_enums.BtTransport.BR_EDR):
                        raise RuntimeError('Failed to call create_bond.')
                        raise RuntimeError('Failed to call create_bond.')


                success, reason = await connect_device
                    success, reason = await create_bond

                    if not success:
                    if not success:
                        raise RuntimeError(f'Failed to connect to the {address}. Reason: {reason}')
                        raise RuntimeError(f'Failed to connect to the {address}. Reason: {reason}')
            finally:
            finally:
+3 −0
Original line number Original line Diff line number Diff line
@@ -44,6 +44,7 @@ class SecurityService(security_grpc_aio.SecurityServicer):
    def __init__(self, server: grpc.aio.Server, bluetooth: bluetooth_module.Bluetooth):
    def __init__(self, server: grpc.aio.Server, bluetooth: bluetooth_module.Bluetooth):
        self.server = server
        self.server = server
        self.bluetooth = bluetooth
        self.bluetooth = bluetooth
        self.manually_confirm = False


    async def OnPairing(self, request: AsyncIterator[security_pb2.PairingEventAnswer],
    async def OnPairing(self, request: AsyncIterator[security_pb2.PairingEventAnswer],
                        context: grpc.ServicerContext) -> AsyncGenerator[security_pb2.PairingEvent, None]:
                        context: grpc.ServicerContext) -> AsyncGenerator[security_pb2.PairingEvent, None]:
@@ -79,6 +80,8 @@ class SecurityService(security_grpc_aio.SecurityServicer):


        observers = []
        observers = []
        try:
        try:
            self.manually_confirm = True

            self.bluetooth.pairing_events = asyncio.Queue()
            self.bluetooth.pairing_events = asyncio.Queue()
            observer = PairingObserver(asyncio.get_running_loop(), {'pairing_events': self.bluetooth.pairing_events})
            observer = PairingObserver(asyncio.get_running_loop(), {'pairing_events': self.bluetooth.pairing_events})
            name = utils.create_observer_name(observer)
            name = utils.create_observer_name(observer)
+5 −4
Original line number Original line Diff line number Diff line
@@ -33,22 +33,23 @@ async def serve(port):
        while True:
        while True:
            bluetooth = bluetooth_module.Bluetooth()
            bluetooth = bluetooth_module.Bluetooth()
            bluetooth.reset()
            bluetooth.reset()

            logging.info("bluetooth initialized")
            logging.info("bluetooth initialized")


            server = grpc.aio.server()
            server = grpc.aio.server()
            host_service = host.HostService(server, bluetooth)
            host_grpc_aio.add_HostServicer_to_server(host_service, server)

            security_service = security.SecurityService(server, bluetooth)
            security_service = security.SecurityService(server, bluetooth)
            security_grpc_aio.add_SecurityServicer_to_server(security_service, server)
            security_grpc_aio.add_SecurityServicer_to_server(security_service, server)


            host_service = host.HostService(server, bluetooth, security_service)
            host_grpc_aio.add_HostServicer_to_server(host_service, server)

            security_storage_service = security.SecurityStorageService(server, bluetooth)
            security_storage_service = security.SecurityStorageService(server, bluetooth)
            security_grpc_aio.add_SecurityStorageServicer_to_server(security_storage_service, server)
            security_grpc_aio.add_SecurityStorageServicer_to_server(security_storage_service, server)


            server.add_insecure_port(f'[::]:{port}')
            server.add_insecure_port(f'[::]:{port}')


            await server.start()
            await server.start()
            logging.info("server started")

            await server.wait_for_termination()
            await server.wait_for_termination()
            bluetooth.cleanup()
            bluetooth.cleanup()
            del bluetooth
            del bluetooth