1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8
9 #include <zephyr/bluetooth/bluetooth.h>
10 #include <zephyr/bluetooth/conn.h>
11 #include <zephyr/bluetooth/gatt.h>
12 #include <zephyr/bluetooth/uuid.h>
13
14 #include <zephyr/settings/settings.h>
15
16 #include <zephyr/logging/log.h>
17
18 #include "testlib/conn.h"
19 #include "testlib/scan.h"
20
21 #include "babblekit/flags.h"
22 #include "babblekit/sync.h"
23 #include "babblekit/testcase.h"
24
25 #include "common.h"
26 #include "bt_settings_hook.h"
27
28 LOG_MODULE_REGISTER(server, LOG_LEVEL_DBG);
29
30 static DEFINE_FLAG(ccc_cfg_changed_flag);
31 static DEFINE_FLAG(disconnected_flag);
32 static DEFINE_FLAG(security_changed_flag);
33
34 static struct bt_conn_cb server_conn_cb;
35
ccc_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)36 static void ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
37 {
38 ARG_UNUSED(attr);
39
40 bool notif_enabled = (value == BT_GATT_CCC_NOTIFY);
41
42 LOG_INF("CCC Update: notification %s", notif_enabled ? "enabled" : "disabled");
43
44 SET_FLAG(ccc_cfg_changed_flag);
45 }
46
47 BT_GATT_SERVICE_DEFINE(test_gatt_service, BT_GATT_PRIMARY_SERVICE(test_service_uuid),
48 BT_GATT_CHARACTERISTIC(test_characteristic_uuid, BT_GATT_CHRC_NOTIFY,
49 BT_GATT_PERM_NONE, NULL, NULL, NULL),
50 BT_GATT_CCC(ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE));
51
disconnected(struct bt_conn * conn,uint8_t reason)52 static void disconnected(struct bt_conn *conn, uint8_t reason)
53 {
54 char addr_str[BT_ADDR_LE_STR_LEN];
55
56 bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
57
58 LOG_DBG("Disconnected: %s (reason 0x%02x)", addr_str, reason);
59
60 SET_FLAG(disconnected_flag);
61 }
62
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)63 static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
64 {
65 char addr_str[BT_ADDR_LE_STR_LEN];
66
67 bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
68
69 TEST_ASSERT(err == 0, "Security update failed: %s level %u err %d", addr_str, level, err);
70
71 LOG_DBG("Security changed: %s level %u", addr_str, level);
72 SET_FLAG(security_changed_flag);
73 }
74
init_server_conn_callbacks(void)75 static void init_server_conn_callbacks(void)
76 {
77 int err;
78
79 server_conn_cb.connected = NULL;
80 server_conn_cb.disconnected = disconnected;
81 server_conn_cb.security_changed = security_changed;
82 server_conn_cb.identity_resolved = NULL;
83
84 err = bt_conn_cb_register(&server_conn_cb);
85 TEST_ASSERT(err == 0, "Failed to set server conn callbacks (err %d)", err);
86 }
87
connect_and_set_security(struct bt_conn ** conn)88 static void connect_and_set_security(struct bt_conn **conn)
89 {
90 int err;
91 bt_addr_le_t client = {};
92
93 err = bt_testlib_scan_find_name(&client, ADVERTISER_NAME);
94 TEST_ASSERT(err == 0, "Failed to start scan (err %d)", err);
95
96 err = bt_testlib_connect(&client, conn);
97 TEST_ASSERT(err == 0, "Failed to initiate connection (err %d)", err);
98
99 err = bt_conn_set_security(*conn, BT_SECURITY_L2);
100 TEST_ASSERT(err == 0, "Failed to set security (err %d)", err);
101
102 WAIT_FOR_FLAG(security_changed_flag);
103 }
104
server_procedure(void)105 void server_procedure(void)
106 {
107 /* Test purpose:
108 *
109 * Verifies that we are deleting GATT settings linked to a peer that we
110 * bonded with.
111 *
112 * Two devices:
113 * - `server`: GATT server, connect and elevate security
114 * - `client`: GATT client, when connected, will subscribe to CCC
115 *
116 * [verdict]
117 * - the server doesn't have settings leftover
118 */
119
120 int err;
121 struct bt_conn *conn = NULL;
122
123 int number_of_settings_left = 0;
124
125 TEST_START("server");
126
127 err = bt_enable(NULL);
128 TEST_ASSERT(err == 0, "Cannot enable Bluetooth (err %d)", err);
129
130 LOG_DBG("Bluetooth initialized");
131
132 err = settings_load();
133 TEST_ASSERT(err == 0, "Failed to load settings (err %d)", err);
134
135 err = bt_unpair(BT_ID_DEFAULT, BT_ADDR_LE_ANY);
136 TEST_ASSERT(err == 0, "(1) Failed to unpair (err %d)", err);
137
138 start_settings_record();
139
140 init_server_conn_callbacks();
141
142 connect_and_set_security(&conn);
143
144 WAIT_FOR_FLAG(ccc_cfg_changed_flag);
145
146 /* Settings may be written to flash on disconnection. */
147 err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
148 TEST_ASSERT(err == 0, "Failed to disconnect (err %d)", err);
149
150 WAIT_FOR_FLAG(disconnected_flag);
151
152 err = bt_unpair(BT_ID_DEFAULT, BT_ADDR_LE_ANY);
153 TEST_ASSERT(err == 0, "(2) Failed to unpair (err %d)", err);
154
155 number_of_settings_left = get_settings_list_size();
156
157 stop_settings_record();
158 settings_list_cleanup();
159
160 if (number_of_settings_left > 0) {
161 TEST_FAIL("'bt_unpair' did not clear the settings properly.");
162 }
163
164 TEST_PASS("server");
165 }
166