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

Commit ba446b71 authored by Jack He's avatar Jack He
Browse files

Cert: Defer unknown DCID in L2capTests

* Sometimes, L2CAP Configuration Request may arrive before
  scid_to_channel map is updated, making it not possible to
  handle such request
* Deferring the request until the connection is made fixes
  the problem
* Adding threading.Lock does not help due to the global interpreter
  lock

Bug: 307877650
Test: m bluetooth_stack_with_facade && gd/cert/run --clean L2capTest
Change-Id: I038d33c7332bbde241bfa68e61ec6f977836e73a
parent a33f9bdc
Loading
Loading
Loading
Loading
+20 −7
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
#   limitations under the License.
#   limitations under the License.


import logging
import logging
from queue import SimpleQueue


from blueberry.tests.gd.cert.behavior import IHasBehaviors, SingleArgumentBehavior, ReplyStage
from blueberry.tests.gd.cert.behavior import IHasBehaviors, SingleArgumentBehavior, ReplyStage
from blueberry.tests.gd.cert.captures import L2capCaptures
from blueberry.tests.gd.cert.captures import L2capCaptures
@@ -151,7 +152,7 @@ class CertL2capControlChannelBehaviors(object):
        def _send_configuration_response(self, request, result=ConfigurationResponseResult.SUCCESS, options=None):
        def _send_configuration_response(self, request, result=ConfigurationResponseResult.SUCCESS, options=None):
            dcid = request.GetDestinationCid()
            dcid = request.GetDestinationCid()
            if dcid not in self.parent.scid_to_channel:
            if dcid not in self.parent.scid_to_channel:
                logging.warning("Received config request with unknown dcid")
                logging.warning("_send_configuration_response with unknown dcid 0x{:X}".format(dcid))
                return
                return
            self.parent.scid_to_channel[dcid].send_configuration_response(request, result, options)
            self.parent.scid_to_channel[dcid].send_configuration_response(request, result, options)


@@ -172,6 +173,7 @@ class CertL2cap(Closable, IHasBehaviors):
            CommandCode.INFORMATION_REQUEST: self._on_information_request_default,
            CommandCode.INFORMATION_REQUEST: self._on_information_request_default,
            CommandCode.INFORMATION_RESPONSE: self._on_information_response_default
            CommandCode.INFORMATION_RESPONSE: self._on_information_response_default
        }
        }
        self.pending_configuration_requests = SimpleQueue()


        self.scid_to_channel = {}
        self.scid_to_channel = {}


@@ -191,8 +193,12 @@ class CertL2cap(Closable, IHasBehaviors):
    def connect_acl(self, remote_addr):
    def connect_acl(self, remote_addr):
        self._acl_manager.initiate_connection(remote_addr)
        self._acl_manager.initiate_connection(remote_addr)
        self._acl = self._acl_manager.complete_outgoing_connection()
        self._acl = self._acl_manager.complete_outgoing_connection()
        self.control_channel = CertL2capChannel(
        self.control_channel = CertL2capChannel(self._device,
            self._device, 1, 1, self._acl.acl_stream, self._acl, control_channel=None)
                                                1,
                                                1,
                                                self._acl.acl_stream,
                                                self._acl,
                                                control_channel=None)
        self._acl.acl_stream.register_callback(self._handle_control_packet)
        self._acl.acl_stream.register_callback(self._handle_control_packet)


    def accept_incoming_connection(self):
    def accept_incoming_connection(self):
@@ -208,11 +214,14 @@ class CertL2cap(Closable, IHasBehaviors):
                                   response.get().GetDestinationCid(), self._acl.acl_stream, self._acl,
                                   response.get().GetDestinationCid(), self._acl.acl_stream, self._acl,
                                   self.control_channel, fcs)
                                   self.control_channel, fcs)
        self.scid_to_channel[scid] = channel
        self.scid_to_channel[scid] = channel
        while not self.pending_configuration_requests.empty():
            l2cap_control_view = self.pending_configuration_requests.get_nowait()
            logging.info("Handling deferred configuration requests")
            self._on_configuration_request_default(l2cap_control_view, defer_unknown_dcid=False)


        return channel
        return channel


    def verify_and_respond_open_channel_from_remote(self, psm=0x33, scid=None, fcs=None):
    def verify_and_respond_open_channel_from_remote(self, psm=0x33, scid=None, fcs=None):

        request = L2capCaptures.ConnectionRequest(psm)
        request = L2capCaptures.ConnectionRequest(psm)
        assertThat(self.control_channel).emits(request)
        assertThat(self.control_channel).emits(request)


@@ -259,18 +268,22 @@ class CertL2cap(Closable, IHasBehaviors):
    def get_control_channel(self):
    def get_control_channel(self):
        return self.control_channel
        return self.control_channel


    # Disable ERTM when exchange extened feature
    # Disable ERTM when exchange extended feature
    def claim_ertm_unsupported(self):
    def claim_ertm_unsupported(self):
        self.support_ertm = False
        self.support_ertm = False


    def _on_connection_response_default(self, l2cap_control_view):
    def _on_connection_response_default(self, l2cap_control_view):
        pass
        pass


    def _on_configuration_request_default(self, l2cap_control_view):
    def _on_configuration_request_default(self, l2cap_control_view, defer_unknown_dcid=True):
        request = l2cap_packets.ConfigurationRequestView(l2cap_control_view)
        request = l2cap_packets.ConfigurationRequestView(l2cap_control_view)
        dcid = request.GetDestinationCid()
        dcid = request.GetDestinationCid()
        if dcid not in self.scid_to_channel:
        if dcid not in self.scid_to_channel:
            logging.warning("Received config request with unknown dcid")
            if defer_unknown_dcid:
                logging.info("Received config request with unknown dcid 0x{:X} deferring".format(dcid))
                self.pending_configuration_requests.put(l2cap_control_view)
            else:
                logging.warning("Received config request with unknown dcid 0x{:X}".format(dcid))
            return
            return
        self._control_behaviors.on_config_req_behavior.run(request)
        self._control_behaviors.on_config_req_behavior.run(request)