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

Commit 81312f12 authored by Chris Manton's avatar Chris Manton
Browse files

Dump SDP control blocks when initiator resource limit reached

Bug: 364657004
Test: atest net_test_stack_sdp
Flag: EXEMPT, Logging Change
Change-Id: Ia3c370fef69d8894d96e54a826da55f2a2f275f3
parent 195c247f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2360,6 +2360,7 @@ cc_test {
        ":TestMockStackBtm",
        ":TestMockStackL2cap",
        ":TestMockStackMetrics",
        "test/sdp/stack_sdp_api_test.cc",
        "test/sdp/stack_sdp_db_test.cc",
        "test/sdp/stack_sdp_parse_test.cc",
        "test/sdp/stack_sdp_test.cc",
+22 −21
Original line number Diff line number Diff line
@@ -31,12 +31,12 @@
#include <string.h>

#include <cstdint>
#include <utility>

#include "internal_include/bt_target.h"
#include "main/shim/dumpsys.h"
#include "stack/include/bt_types.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/sdp_api.h"
#include "stack/include/sdpdefs.h"
#include "stack/sdp/internal/sdp_api.h"
#include "stack/sdp/sdpint.h"
@@ -86,7 +86,7 @@ bool SDP_InitDiscoveryDb(tSDP_DISCOVERY_DB* p_db, uint32_t len, uint16_t num_uui
    return false;
  }

  memset(p_db, 0, (size_t)len);
  memset(p_db, 0, static_cast<size_t>(len));

  p_db->mem_size = len - sizeof(tSDP_DISCOVERY_DB);
  p_db->mem_free = p_db->mem_size;
@@ -145,6 +145,8 @@ bool SDP_ServiceSearchRequest(const RawAddress& bd_addr, tSDP_DISCOVERY_DB* p_db
  /* Specific BD address */
  tCONN_CB* p_ccb = sdp_conn_originate(bd_addr);
  if (!p_ccb) {
    log::warn("no spare CCB for peer:{} max:{}", bd_addr, kMaxSdpConnections);
    sdpu_dump_all_ccb();
    return false;
  }

@@ -174,6 +176,8 @@ bool SDP_ServiceSearchAttributeRequest(const RawAddress& bd_addr, tSDP_DISCOVERY
  /* Specific BD address */
  tCONN_CB* p_ccb = sdp_conn_originate(bd_addr);
  if (!p_ccb) {
    log::warn("no spare CCB for peer:{} max:{}", bd_addr, kMaxSdpConnections);
    sdpu_dump_all_ccb();
    return false;
  }

@@ -205,6 +209,8 @@ bool SDP_ServiceSearchAttributeRequest2(
  /* Specific BD address */
  tCONN_CB* p_ccb = sdp_conn_originate(bd_addr);
  if (!p_ccb) {
    log::warn("no spare CCB for peer:{} max:{}", bd_addr, kMaxSdpConnections);
    sdpu_dump_all_ccb();
    return false;
  }

@@ -275,13 +281,11 @@ bool SDP_FindServiceUUIDInRec(const tSDP_DISC_REC* p_rec, Uuid* p_uuid) {
          }

          return true;
        }

        } else {
          /* Checking for Toyota G Block Car Kit:
           **  This car kit puts an extra data element sequence
           **  where the UUID is suppose to be!!!
           */
        else {
          if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE) {
            /* Look through data element sequence until no more UUIDs */
            for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr; p_extra_sattr;
@@ -404,17 +408,14 @@ tSDP_DISC_REC* SDP_FindServiceInDb(const tSDP_DISCOVERY_DB* p_db, uint16_t servi

          if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE &&
              (service_uuid == 0 || (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2 &&
                                     p_sattr->attr_value.v.u16 == service_uuid)))
                                     p_sattr->attr_value.v.u16 == service_uuid))) {
            /* for a specific uuid, or any one */
          {
            return p_rec;
          }

          } else {
            /* Checking for Toyota G Block Car Kit:
             **  This car kit puts an extra data element sequence
             **  where the UUID is suppose to be!!!
             */
          else {
            if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE) {
              /* Look through data element sequence until no more UUIDs */
              for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr; p_extra_sattr;
@@ -705,8 +706,8 @@ bool SDP_FindProfileVersionInRec(const tSDP_DISC_REC* p_rec, uint16_t profile_uu

              return true;
            } else {
              return false; /* The type and/or size was not valid for the
                               profile list version */
              return false;  // The type and/or size was not valid for the
                             //   profile list version
            }
          }
        }
+3 −3
Original line number Diff line number Diff line
@@ -59,7 +59,8 @@ static void sdp_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid, uint1
                            uint8_t /* l2cap_id */) {
  tCONN_CB* p_ccb = sdpu_allocate_ccb();
  if (p_ccb == NULL) {
    log::warn("no spare CCB for peer:{} cid:{}", bd_addr, l2cap_cid);
    log::warn("no spare CCB for peer:{} max:{} cid:{}", bd_addr,
              static_cast<size_t>(SDP_MAX_CONNECTIONS), l2cap_cid);
    sdpu_dump_all_ccb();
    return;
  }
@@ -268,7 +269,6 @@ tCONN_CB* sdp_conn_originate(const RawAddress& bd_addr) {
  /* Allocate a new CCB. Return if none available. */
  tCONN_CB* p_ccb = sdpu_allocate_ccb();
  if (p_ccb == NULL) {
    log::warn("no spare CCB for peer {}", bd_addr);
    return NULL;
  }

@@ -376,7 +376,7 @@ static void sdp_disconnect_cfm(uint16_t l2cap_cid, uint16_t /* result */) {
 *
 ******************************************************************************/
void sdp_conn_timer_timeout(void* data) {
  tCONN_CB& ccb = *(tCONN_CB*)data;
  tCONN_CB& ccb = *(static_cast<tCONN_CB*>(data));

  log::verbose("SDP - CCB timeout in state: {}  CID: 0x{:x}", sdp_state_text(ccb.con_state),
               ccb.connection_id);
+1 −1
Original line number Diff line number Diff line
@@ -244,7 +244,7 @@ void sdp_disconnect(tCONN_CB* p_ccb, tSDP_REASON reason);

void sdp_conn_timer_timeout(void* data);

tCONN_CB* sdp_conn_originate(const RawAddress& bd_addr);
[[nodiscard]] tCONN_CB* sdp_conn_originate(const RawAddress& bd_addr);

/* Functions provided by sdp_utils.cc
 */
+130 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include <stdlib.h>

#include <cstddef>
#include <cstdint>
#include <memory>

#include "btif/include/btif_common.h"
#include "osi/include/allocator.h"
#include "stack/include/sdp_api.h"
#include "stack/sdp/sdpint.h"
#include "test/fake/fake_osi.h"
#include "test/mock/mock_osi_allocator.h"
#include "test/mock/mock_stack_l2cap_api.h"

#ifndef BT_DEFAULT_BUFFER_SIZE
#define BT_DEFAULT_BUFFER_SIZE (4096 + 16)
#endif

namespace {
constexpr uint8_t kSDP_MAX_CONNECTIONS = static_cast<uint8_t>(SDP_MAX_CONNECTIONS);

const RawAddress kRawAddress = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6});
int L2CA_ConnectReqWithSecurity_cid = 0x42;
tSDP_DISCOVERY_DB* sdp_db = nullptr;

class StackSdpWithMocksTest : public ::testing::Test {
protected:
  void SetUp() override {
    fake_osi_ = std::make_unique<::test::fake::FakeOsi>();

    test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity.body =
            [](uint16_t /* psm */, const RawAddress& /* p_bd_addr */, uint16_t /* sec_level */) {
              return ++L2CA_ConnectReqWithSecurity_cid;
            };
    test::mock::stack_l2cap_api::L2CA_DataWrite.body = [](uint16_t /* cid */,
                                                          BT_HDR* p_data) -> tL2CAP_DW_RESULT {
      osi_free_and_reset(reinterpret_cast<void**>(&p_data));
      return tL2CAP_DW_RESULT::FAILED;
    };
    test::mock::stack_l2cap_api::L2CA_DisconnectReq.body = [](uint16_t /* cid */) { return true; };
    test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity.body =
            [](uint16_t psm, const tL2CAP_APPL_INFO& /* p_cb_info */, bool /* enable_snoop */,
               tL2CAP_ERTM_INFO* /* p_ertm_info */, uint16_t /* my_mtu */,
               uint16_t /* required_remote_mtu */, uint16_t /* sec_level */) { return psm; };
  }

  void TearDown() override {
    test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity = {};
    test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity = {};
    test::mock::stack_l2cap_api::L2CA_DataWrite = {};
    test::mock::stack_l2cap_api::L2CA_DisconnectReq = {};

    fake_osi_.reset();
  }

  std::unique_ptr<test::fake::FakeOsi> fake_osi_;
};

class StackSdpApiTest : public StackSdpWithMocksTest {
protected:
  void SetUp() override {
    StackSdpWithMocksTest::SetUp();
    sdp_init();
    sdp_db = static_cast<tSDP_DISCOVERY_DB*>(osi_malloc(BT_DEFAULT_BUFFER_SIZE));
  }

  void TearDown() override {
    osi_free(sdp_db);
    sdp_free();
    StackSdpWithMocksTest::TearDown();
  }
};

}  // namespace

TEST_F(StackSdpApiTest, nop) {}

TEST_F(StackSdpApiTest, SDP_ServiceSearchRequest) {
  tSDP_DISCOVERY_DB db;
  for (uint8_t i = 0; i < kSDP_MAX_CONNECTIONS; i++) {
    RawAddress bd_addr = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, i});
    ASSERT_NE(nullptr, sdp_conn_originate(bd_addr));
  }
  ASSERT_FALSE(bluetooth::legacy::stack::sdp::get_legacy_stack_sdp_api()
                       ->service.SDP_ServiceSearchRequest(
                               kRawAddress, &db,
                               [](const RawAddress& /* bd_addr */, tSDP_RESULT /* result */) {}));
}

TEST_F(StackSdpApiTest, SDP_ServiceSearchAttributeRequest) {
  tSDP_DISCOVERY_DB db;
  for (uint8_t i = 0; i < kSDP_MAX_CONNECTIONS; i++) {
    RawAddress bd_addr = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, i});
    ASSERT_NE(nullptr, sdp_conn_originate(bd_addr));
  }
  ASSERT_FALSE(bluetooth::legacy::stack::sdp::get_legacy_stack_sdp_api()
                       ->service.SDP_ServiceSearchAttributeRequest(
                               kRawAddress, &db,
                               [](const RawAddress& /* bd_addr */, tSDP_RESULT /* result */) {}));
}

TEST_F(StackSdpApiTest, SDP_ServiceSearchAttributeRequest2) {
  tSDP_DISCOVERY_DB db;
  for (uint8_t i = 0; i < kSDP_MAX_CONNECTIONS; i++) {
    RawAddress bd_addr = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, i});
    ASSERT_NE(nullptr, sdp_conn_originate(bd_addr));
  }
  ASSERT_FALSE(bluetooth::legacy::stack::sdp::get_legacy_stack_sdp_api()
                       ->service.SDP_ServiceSearchAttributeRequest2(
                               kRawAddress, &db,
                               base::BindRepeating([](const RawAddress& /* bd_addr */,
                                                      tSDP_RESULT /* result */) {})));
}