xref: /btstack/test/gatt_server/gatt_server_test.cpp (revision 98f1394d9d4c33f501ec5dcff54d145a92013c5e)
1 
2 // *****************************************************************************
3 //
4 // test rfcomm query tests
5 //
6 // *****************************************************************************
7 
8 
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "CppUTest/TestHarness.h"
15 #include "CppUTest/CommandLineTestRunner.h"
16 
17 #include "hci.h"
18 #include "ble/att_db.h"
19 #include "ble/att_db_util.h"
20 #include "ble/att_server.h"
21 #include "btstack_util.h"
22 #include "bluetooth.h"
23 #include "btstack_tlv.h"
24 #include "mock_btstack_tlv.h"
25 
26 #include "bluetooth_gatt.h"
27 
28 static uint8_t battery_level = 100;
29 static const uint8_t uuid128_with_bluetooth_base[] = { 0x00, 0x00, 0xBB, 0xBB, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
30 static const uint8_t uuid128_no_bluetooth_base[] =   { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xAA, 0xAA, 0x00, 0x00 };
31 
32 extern "C" void l2cap_can_send_fixed_channel_packet_now_set_status(uint8_t status);
33 extern "C" void mock_call_att_server_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
34 extern "C" void hci_setup_le_connection(uint16_t con_handle);
35 extern "C" void mock_call_att_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
36 extern "C" void mock_l2cap_set_max_mtu(uint16_t mtu);
37 
38 static uint8_t att_request[255];
39 static uint16_t att_write_request(uint16_t request_type, uint16_t attribute_handle, uint16_t value_length, const uint8_t * value){
40     att_request[0] = request_type;
41     little_endian_store_16(att_request, 1, attribute_handle);
42     (void)memcpy(&att_request[3], value, value_length);
43     return 3 + value_length;
44 }
45 
46 static uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
47     UNUSED(connection_handle);
48     UNUSED(att_handle);
49     UNUSED(offset);
50     UNUSED(buffer);
51     UNUSED(buffer_size);
52 
53     return 0;
54 }
55 
56 static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
57     UNUSED(connection_handle);
58     UNUSED(att_handle);
59     UNUSED(transaction_mode);
60     UNUSED(offset);
61     UNUSED(buffer);
62     UNUSED(buffer_size);
63 
64     return 0;
65 }
66 
67 static void att_client_indication_callback(void * context){
68 }
69 static void att_client_notification_callback(void * context){
70 }
71 static void att_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
72 }
73 
74 
75 TEST_GROUP(ATT_SERVER){
76     uint16_t att_con_handle;
77     mock_btstack_tlv_t tlv_context;
78     const btstack_tlv_t * tlv_impl;
79     btstack_context_callback_registration_t indication_callback;
80     btstack_context_callback_registration_t notification_callback;
81 
82     void setup(void){
83         att_con_handle = 0x01;
84 
85         hci_setup_le_connection(att_con_handle);
86 
87         tlv_impl = mock_btstack_tlv_init_instance(&tlv_context);
88         btstack_tlv_set_instance(tlv_impl, &tlv_context);
89 
90         l2cap_can_send_fixed_channel_packet_now_set_status(1);
91         indication_callback.callback = &att_client_indication_callback;
92         notification_callback.callback = &att_client_notification_callback;
93 
94         // init att db util and add a service and characteristic
95         att_db_util_init();
96         // 0x180F
97         att_db_util_add_service_uuid16(ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE);
98         // 0x2A19
99         att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL,       ATT_PROPERTY_WRITE | ATT_PROPERTY_READ | ATT_PROPERTY_INDICATE, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
100         // 0x2A1B
101         att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL_STATE, ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
102         // 0x2A1A
103         att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_POWER_STATE, ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY, ATT_SECURITY_AUTHENTICATED, ATT_SECURITY_AUTHENTICATED, &battery_level, 1);
104         // 0x2A49
105         att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BLOOD_PRESSURE_FEATURE, ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_READ | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
106         // 0x2A35
107         att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BLOOD_PRESSURE_MEASUREMENT, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_AUTHENTICATED, ATT_SECURITY_AUTHENTICATED, &battery_level, 1);
108 
109 
110         att_db_util_add_characteristic_uuid128(uuid128_no_bluetooth_base, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
111         // 0x2A38btstack_tlv_set_instance
112         att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BODY_SENSOR_LOCATION, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
113 
114 
115         att_db_util_add_characteristic_uuid128(uuid128_with_bluetooth_base, ATT_PROPERTY_WRITE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
116         // 0x2AAB
117         att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_CGM_SESSION_RUN_TIME, ATT_PROPERTY_WRITE_WITHOUT_RESPONSE | ATT_PROPERTY_DYNAMIC | ATT_PROPERTY_NOTIFY, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
118         // 0x2A5C
119         att_db_util_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_CSC_FEATURE, ATT_PROPERTY_AUTHENTICATED_SIGNED_WRITE | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_NONE, ATT_SECURITY_NONE, &battery_level, 1);
120         // setup ATT server
121         att_server_init(att_db_util_get_address(), att_read_callback, att_write_callback);
122     }
123 
124     void teardown(void) {
125         mock_btstack_tlv_deinit(&tlv_context);
126         hci_deinit();
127     }
128 };
129 
130 
131 TEST(ATT_SERVER, gatt_server_get_value_handle_for_characteristic_with_uuid16){
132     // att_dump_attributes();
133     uint16_t value_handle;
134 
135     // start handle > value handle
136     value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0xf000, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
137     CHECK_EQUAL(0, value_handle);
138 
139     // end handle < value handle
140     value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0x02, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
141     CHECK_EQUAL(0, value_handle);
142 
143     // search value handle for unknown UUID
144     value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, 0xffff);
145     CHECK_EQUAL(0, value_handle);
146 
147     value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, 0);
148     CHECK_EQUAL(0, value_handle);
149 
150     // search value handle after one with uuid128_no_bluetooth_base
151     value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BODY_SENSOR_LOCATION);
152     CHECK_EQUAL(0x0014, value_handle);
153 
154     // search value handle after one with uuid128_with_bluetooth_base
155     value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_CGM_SESSION_RUN_TIME);
156     CHECK_EQUAL(0x001a, value_handle);
157 
158     // search value handle registered with bluetooth_base
159     value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, 0xbbbb);
160     CHECK_EQUAL(0x0017, value_handle);
161 
162     // correct read
163     value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
164     CHECK_EQUAL(0x03, value_handle);
165 }
166 
167 
168 TEST(ATT_SERVER, att_server_indicate){
169     static uint8_t value[] = {0x55};
170     uint16_t value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
171     uint8_t status;
172 
173     // invalid connection handle
174     status = att_server_indicate(0x50, value_handle, &value[0], 0);
175     CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status);
176 
177     // L2CAP cannot send
178     l2cap_can_send_fixed_channel_packet_now_set_status(0);
179     status = att_server_indicate(att_con_handle, value_handle, &value[0], 0);
180     CHECK_EQUAL(BTSTACK_ACL_BUFFERS_FULL, status);
181     l2cap_can_send_fixed_channel_packet_now_set_status(1);
182 
183     // correct command
184     status = att_server_indicate(att_con_handle, value_handle, &value[0], 0);
185     CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
186 
187     // already in progress
188     status = att_server_indicate(att_con_handle, value_handle, &value[0], 0);
189     CHECK_EQUAL(ATT_HANDLE_VALUE_INDICATION_IN_PROGRESS, status);
190 }
191 
192 TEST(ATT_SERVER, att_server_notify){
193     static uint8_t value[] = {0x55};
194     uint16_t value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
195     uint8_t status;
196 
197     // invalid connection handle
198     status = att_server_notify(0x50, value_handle, &value[0], 0);
199     CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status);
200 
201     // L2CAP cannot send
202     l2cap_can_send_fixed_channel_packet_now_set_status(0);
203     status = att_server_notify(att_con_handle, value_handle, &value[0], 0);
204     CHECK_EQUAL(BTSTACK_ACL_BUFFERS_FULL, status);
205     l2cap_can_send_fixed_channel_packet_now_set_status(1);
206 
207     // correct command
208     status = att_server_notify(att_con_handle, value_handle, &value[0], 0);
209     CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
210 }
211 
212 TEST(ATT_SERVER, att_server_get_mtu){
213     // invalid connection handle
214     uint8_t mtu = att_server_get_mtu(0x50);
215     CHECK_EQUAL(0, mtu);
216 
217     mtu = att_server_get_mtu(att_con_handle);
218     CHECK_EQUAL(23, mtu);
219 }
220 
221 TEST(ATT_SERVER, att_server_request_can_send_now_event){
222     att_server_request_can_send_now_event(att_con_handle);
223 }
224 
225 TEST(ATT_SERVER, att_server_can_send_packet_now){
226     int status = att_server_can_send_packet_now(att_con_handle);
227     CHECK_EQUAL(1, status);
228 
229     status = att_server_can_send_packet_now(0x50);
230     CHECK_EQUAL(0, status);
231 }
232 
233 TEST(ATT_SERVER, att_server_request_to_send_indication){
234     int status = att_server_request_to_send_indication(&indication_callback, 0x55);
235     CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status);
236 
237     l2cap_can_send_fixed_channel_packet_now_set_status(0);
238 
239     status = att_server_request_to_send_indication(&indication_callback, att_con_handle);
240     CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
241 
242     status = att_server_request_to_send_indication(&indication_callback, att_con_handle);
243     CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status);
244 }
245 
246 TEST(ATT_SERVER, att_server_request_to_send_notification){
247     int status = att_server_request_to_send_notification(&notification_callback, 0x55);
248     CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status);
249 
250     l2cap_can_send_fixed_channel_packet_now_set_status(0);
251 
252     status = att_server_request_to_send_notification(&notification_callback, att_con_handle);
253     CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
254 
255     status = att_server_request_to_send_notification(&notification_callback, att_con_handle);
256     CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status);
257 }
258 
259 TEST(ATT_SERVER, att_server_register_can_send_now_callback){
260     int status = att_server_register_can_send_now_callback(&notification_callback, 0x55);
261     CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status);
262 
263     att_server_register_packet_handler(&att_event_packet_handler);
264 }
265 
266 TEST(ATT_SERVER, opcode_ATT_WRITE_REQUEST){
267     uint16_t value_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
268     uint8_t buffer[] = {1, 0};
269 
270     uint16_t att_request_len = att_write_request(ATT_WRITE_REQUEST, value_handle, sizeof(buffer), buffer);
271     mock_call_att_server_packet_handler(ATT_DATA_PACKET, att_con_handle, &att_request[0], att_request_len);
272 }
273 
274 TEST(ATT_SERVER, connection_complete_event){
275     uint8_t buffer[21];
276     buffer[0] = HCI_EVENT_LE_META;
277     buffer[1] = 19;
278     buffer[2] = HCI_SUBEVENT_LE_CONNECTION_COMPLETE;
279 
280     // call with wrong con_handle
281     little_endian_store_16(buffer,4,HCI_CON_HANDLE_INVALID);
282     mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer));
283 
284     // call with correct con_handle
285     little_endian_store_16(buffer,4,att_con_handle);
286     mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer));
287 
288     // use max MTU > ATT_REQUEST_BUFFER_SIZE
289     mock_l2cap_set_max_mtu(ATT_REQUEST_BUFFER_SIZE + 10);
290     mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer));
291 
292     // wrong subevent
293     buffer[2] = 0xFF;
294     mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer));
295 }
296 
297 TEST(ATT_SERVER, connection_disconnect_complete_event) {
298     uint8_t buffer[6];
299     buffer[0] = HCI_EVENT_DISCONNECTION_COMPLETE;
300     buffer[1] = 19;
301     buffer[2] = 0;
302 
303     // call with wrong con_handle
304     hci_setup_le_connection(att_con_handle);
305     little_endian_store_16(buffer, 3, HCI_CON_HANDLE_INVALID);
306     mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer));
307 
308     // call with correct con_handle
309     hci_setup_le_connection(att_con_handle);
310     little_endian_store_16(buffer, 3, att_con_handle);
311     mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer));
312 
313     hci_setup_le_connection(att_con_handle);
314     static uint8_t value[] = {0x55};
315     uint16_t value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
316     l2cap_can_send_fixed_channel_packet_now_set_status(1);
317     // correct command
318     uint8_t status = att_server_indicate(att_con_handle, value_handle, &value[0], 0);
319     CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
320 
321     mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer));
322 }
323 
324 
325 
326 int main (int argc, const char * argv[]){
327     return CommandLineTestRunner::RunAllTests(argc, argv);
328 }
329