1 /******************************************************************************
2 *
3 * Copyright 2014 Google, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #include "hci/include/packet_fragmenter.h"
20
21 #include <gtest/gtest.h>
22 #include <stdint.h>
23
24 #include "hci/include/hci_layer.h"
25 #include "internal_include/bt_target.h"
26 #include "osi/include/allocator.h"
27 #include "osi/include/osi.h"
28 #include "stack/include/bt_hdr.h"
29 #include "test_stubs.h"
30
31 #ifndef HCI_ISO_PREAMBLE_SIZE
32 #define HCI_ISO_PREAMBLE_SIZE 4
33 #endif
34
35 DECLARE_TEST_MODES(init, iso_no_reassembly, iso_reassembly, iso_fragmentation,
36 iso_no_fragmentation);
37
38 #define LOCAL_BLE_CONTROLLER_ID 1
39
40 static const char* sample_data =
41 "At this point they came in sight of thirty forty windmills that there are "
42 "on plain, and "
43 "as soon as Don Quixote saw them he said to his squire, \"Fortune is "
44 "arranging matters "
45 "for us better than we could have shaped our desires ourselves, for look "
46 "there, friend "
47 "Sancho Panza, where thirty or more monstrous giants present themselves, "
48 "all of whom I "
49 "mean to engage in battle and slay, and with whose spoils we shall begin "
50 "to make our "
51 "fortunes; for this is righteous warfare, and it is God's good service to "
52 "sweep so evil "
53 "a breed from off the face of the earth.\"";
54
55 static const char* small_sample_data = "\"What giants?\" said Sancho Panza.";
56 static const uint16_t test_iso_handle_complete_with_ts =
57 (0x0666 | (0x0002 << 12) | (0x0001 << 14));
58 static const uint16_t test_iso_handle_complete_without_ts =
59 (0x0666 | (0x0002 << 12));
60 static const uint16_t test_iso_handle_start_with_ts = (0x0666 | (0x0001 << 14));
61 static const uint16_t test_iso_handle_start_without_ts =
62 (0x0666); // Also base handle
63 static const uint16_t test_iso_handle_continuation = (0x0666 | (0x0001 << 12));
64 static const uint16_t test_iso_handle_end = (0x0666 | (0x0003 << 12));
65
66 static int packet_index;
67 static unsigned int data_size_sum;
68
69 static const packet_fragmenter_t* fragmenter;
70
71 static uint32_t iso_timestamp = 0x32122321;
72 static uint16_t iso_packet_seq = 0x1291;
73 static bool iso_has_ts = true;
74
manufacture_packet_for_fragmentation(uint16_t event,const char * data)75 static BT_HDR* manufacture_packet_for_fragmentation(uint16_t event,
76 const char* data) {
77 uint16_t data_length = strlen(data);
78 uint16_t size = data_length;
79 if (event == MSG_STACK_TO_HC_HCI_ISO) {
80 size += 8; // handle (2), length (2), packet_seq (2), sdu_len(2)
81 if (iso_has_ts) {
82 size += 4;
83 }
84 }
85
86 BT_HDR* packet = (BT_HDR*)osi_malloc(size + sizeof(BT_HDR));
87 packet->len = size;
88 packet->offset = 0;
89 packet->event = event;
90 packet->layer_specific = 0;
91 uint8_t* packet_data = packet->data;
92
93 if (event == MSG_STACK_TO_HC_HCI_ISO) {
94 if (iso_has_ts) {
95 packet->layer_specific |= BT_ISO_HDR_CONTAINS_TS;
96 UINT16_TO_STREAM(packet_data, test_iso_handle_start_with_ts);
97 UINT16_TO_STREAM(packet_data, data_length + 8);
98 UINT32_TO_STREAM(packet_data, iso_timestamp);
99 } else {
100 UINT16_TO_STREAM(packet_data, test_iso_handle_start_without_ts);
101 UINT16_TO_STREAM(packet_data, data_length + 4);
102 }
103 UINT16_TO_STREAM(packet_data, iso_packet_seq);
104 UINT16_TO_STREAM(packet_data, data_length);
105 }
106
107 memcpy(packet_data, data, data_length);
108 return packet;
109 }
110
expect_packet_fragmented(uint16_t event,int max_acl_data_size,BT_HDR * packet,const char * expected_data,bool send_complete)111 static void expect_packet_fragmented(uint16_t event, int max_acl_data_size,
112 BT_HDR* packet, const char* expected_data,
113 bool send_complete) {
114 uint8_t* data = packet->data + packet->offset;
115 int expected_data_offset;
116 int length_to_check;
117
118 if (event == MSG_STACK_TO_HC_HCI_ISO) {
119 uint16_t handle;
120 uint16_t length;
121
122 STREAM_TO_UINT16(handle, data);
123 STREAM_TO_UINT16(length, data);
124
125 int length_remaining = strlen(expected_data) - data_size_sum;
126 int packet_data_length = packet->len - HCI_ISO_PREAMBLE_SIZE;
127
128 if (packet_index == 0) {
129 uint8_t hdr_size = 8; // ts, packet_seq, len
130
131 if (iso_has_ts) {
132 uint32_t timestamp;
133 STREAM_TO_UINT32(timestamp, data);
134 ASSERT_EQ(timestamp, iso_timestamp);
135
136 if (send_complete)
137 ASSERT_EQ(test_iso_handle_complete_with_ts, handle);
138 else
139 ASSERT_EQ(test_iso_handle_start_with_ts, handle);
140 } else {
141 if (send_complete)
142 ASSERT_EQ(test_iso_handle_complete_without_ts, handle);
143 else
144 ASSERT_EQ(test_iso_handle_start_without_ts, handle);
145 hdr_size -= 4;
146 }
147
148 uint16_t packet_seq;
149 STREAM_TO_UINT16(packet_seq, data);
150 ASSERT_EQ(packet_seq, iso_packet_seq);
151
152 uint16_t iso_sdu_length;
153 STREAM_TO_UINT16(iso_sdu_length, data);
154
155 ASSERT_EQ(iso_sdu_length, strlen(expected_data));
156
157 length_to_check = packet_data_length - hdr_size;
158 } else {
159 if (!send_complete)
160 ASSERT_EQ(test_iso_handle_continuation, handle);
161 else
162 ASSERT_EQ(test_iso_handle_end, handle);
163
164 length_to_check = packet_data_length;
165 }
166
167 if (length_remaining > max_acl_data_size)
168 ASSERT_EQ(max_acl_data_size, packet_data_length);
169
170 expected_data_offset = packet_index * max_acl_data_size;
171 if (expected_data_offset > 0) {
172 if (iso_has_ts) {
173 expected_data_offset -= 8;
174 } else {
175 expected_data_offset -= 4;
176 }
177 }
178 packet_index++;
179 } else {
180 length_to_check = strlen(expected_data);
181 expected_data_offset = 0;
182 }
183
184 for (int i = 0; i < length_to_check; i++) {
185 EXPECT_EQ(expected_data[expected_data_offset + i], data[i]);
186 data_size_sum++;
187 }
188
189 if (event == MSG_STACK_TO_HC_HCI_ISO)
190 EXPECT_TRUE(send_complete == (data_size_sum == strlen(expected_data)));
191
192 if (send_complete) osi_free(packet);
193 }
194
manufacture_iso_packet_and_then_reassemble(uint16_t event,uint16_t iso_size,const char * data)195 static void manufacture_iso_packet_and_then_reassemble(uint16_t event,
196 uint16_t iso_size,
197 const char* data) {
198 uint16_t data_length = strlen(data);
199 uint16_t total_length;
200 uint16_t length_sent = 0;
201 uint16_t iso_length = data_length;
202 BT_HDR* packet;
203 uint8_t* packet_data;
204 uint8_t hdr_size = 4; // packet seq, sdu len
205
206 // ISO length (2), packet seq (2), optional timestamp (4)
207 total_length = data_length + 4;
208 if (iso_has_ts) total_length += 4;
209
210 do {
211 int length_to_send = (length_sent + (iso_size - 4) < total_length)
212 ? (iso_size - 4)
213 : (total_length - length_sent);
214
215 packet = (BT_HDR*)osi_malloc(length_to_send + 4 + sizeof(BT_HDR));
216 packet_data = packet->data;
217 packet->len = length_to_send + 4;
218 packet->offset = 0;
219 packet->event = event;
220 packet->layer_specific = 0;
221
222 bool is_complete = length_to_send == total_length;
223
224 if (length_sent == 0) { // first packet
225 if (iso_has_ts) {
226 hdr_size += 4;
227 if (is_complete) {
228 UINT16_TO_STREAM(packet_data, test_iso_handle_complete_with_ts);
229 } else {
230 UINT16_TO_STREAM(packet_data, test_iso_handle_start_with_ts);
231 }
232 } else {
233 if (is_complete) {
234 UINT16_TO_STREAM(packet_data, test_iso_handle_complete_without_ts);
235 } else {
236 UINT16_TO_STREAM(packet_data, test_iso_handle_start_without_ts);
237 }
238 }
239
240 UINT16_TO_STREAM(packet_data, length_to_send);
241
242 if (iso_has_ts) {
243 UINT32_TO_STREAM(packet_data, iso_timestamp);
244 }
245
246 UINT16_TO_STREAM(packet_data, iso_packet_seq);
247 UINT16_TO_STREAM(packet_data, iso_length);
248 memcpy(packet_data, data, length_to_send - hdr_size);
249 } else {
250 if (length_sent + length_to_send == total_length) {
251 UINT16_TO_STREAM(packet_data, test_iso_handle_end);
252 } else {
253 UINT16_TO_STREAM(packet_data, test_iso_handle_continuation);
254 }
255 UINT16_TO_STREAM(packet_data, length_to_send);
256 memcpy(packet_data, data + length_sent - hdr_size, length_to_send);
257 }
258
259 length_sent += length_to_send;
260 fragmenter->reassemble_and_dispatch(packet);
261 } while (length_sent < total_length);
262 }
263
manufacture_packet_and_then_reassemble(uint16_t event,uint16_t packet_size,const char * data)264 static void manufacture_packet_and_then_reassemble(uint16_t event,
265 uint16_t packet_size,
266 const char* data) {
267 uint16_t data_length = strlen(data);
268
269 if (event == MSG_HC_TO_STACK_HCI_ISO) {
270 manufacture_iso_packet_and_then_reassemble(event, packet_size, data);
271 } else {
272 BT_HDR* packet = (BT_HDR*)osi_malloc(data_length + sizeof(BT_HDR));
273 packet->len = data_length;
274 packet->offset = 0;
275 packet->event = event;
276 packet->layer_specific = 0;
277 memcpy(packet->data, data, data_length);
278
279 fragmenter->reassemble_and_dispatch(packet);
280 }
281 }
282
expect_packet_reassembled_iso(uint16_t event,BT_HDR * packet,const char * expected_data,uint32_t expected_timestamp,uint16_t expected_packet_seq,bool is_complete=false)283 static void expect_packet_reassembled_iso(uint16_t event, BT_HDR* packet,
284 const char* expected_data,
285 uint32_t expected_timestamp,
286 uint16_t expected_packet_seq,
287 bool is_complete = false) {
288 uint16_t expected_data_length = strlen(expected_data);
289 uint8_t* data = packet->data;
290 uint8_t hdr_size = 8;
291 uint16_t handle;
292 uint16_t length;
293 uint16_t iso_length;
294 uint32_t timestamp;
295 uint16_t packet_seq;
296
297 ASSERT_EQ(event, MSG_HC_TO_STACK_HCI_ISO);
298
299 STREAM_TO_UINT16(handle, data);
300 STREAM_TO_UINT16(length, data);
301 if (iso_has_ts) {
302 STREAM_TO_UINT32(timestamp, data);
303 ASSERT_TRUE((packet->layer_specific & BT_ISO_HDR_CONTAINS_TS) != 0);
304 ASSERT_EQ(timestamp, expected_timestamp);
305 ASSERT_EQ(is_complete ? test_iso_handle_complete_with_ts
306 : test_iso_handle_start_with_ts,
307 handle);
308 } else {
309 ASSERT_TRUE((packet->layer_specific & BT_ISO_HDR_CONTAINS_TS) == 0);
310 ASSERT_EQ(is_complete ? test_iso_handle_complete_without_ts
311 : test_iso_handle_start_without_ts,
312 handle);
313 hdr_size -= 4;
314 }
315
316 ASSERT_EQ(expected_data_length + hdr_size, length);
317
318 STREAM_TO_UINT16(packet_seq, data);
319 ASSERT_EQ(packet_seq, expected_packet_seq);
320
321 STREAM_TO_UINT16(iso_length, data);
322 ASSERT_EQ(expected_data_length, iso_length);
323
324 for (int i = 0; i < expected_data_length; i++) {
325 ASSERT_EQ(expected_data[i], data[i]);
326 data_size_sum++;
327 }
328
329 osi_free(packet);
330 }
331
332 STUB_FUNCTION(void, fragmented_callback, (BT_HDR * packet, bool send_complete))
DURING(iso_fragmentation)333 DURING(iso_fragmentation) {
334 expect_packet_fragmented(MSG_STACK_TO_HC_HCI_ISO, 10, packet, sample_data,
335 send_complete);
336 return;
337 }
338
DURING(iso_no_fragmentation)339 DURING(iso_no_fragmentation) {
340 expect_packet_fragmented(MSG_STACK_TO_HC_HCI_ISO, 42, packet,
341 small_sample_data, send_complete);
342 return;
343 }
344
345 UNEXPECTED_CALL;
346 }
347
348 STUB_FUNCTION(void, reassembled_callback, (BT_HDR * packet))
349 DURING(iso_reassembly) AT_CALL(0) {
350 expect_packet_reassembled_iso(MSG_HC_TO_STACK_HCI_ISO, packet, sample_data,
351 iso_timestamp, iso_packet_seq);
352 return;
353 }
354
355 DURING(iso_no_reassembly) AT_CALL(0) {
356 expect_packet_reassembled_iso(MSG_HC_TO_STACK_HCI_ISO, packet,
357 small_sample_data, iso_timestamp,
358 iso_packet_seq, true);
359 return;
360 }
361
362 UNEXPECTED_CALL;
363 }
364
365 STUB_FUNCTION(uint16_t, get_iso_data_size, (void))
366 DURING(iso_no_fragmentation) return 42;
367 DURING(iso_fragmentation) return 10;
368
369 UNEXPECTED_CALL;
370 return 0;
371 }
372
373 static void reset_for(TEST_MODES_T next) {
374 RESET_CALL_COUNT(fragmented_callback);
375 RESET_CALL_COUNT(reassembled_callback);
376 CURRENT_TEST_MODE = next;
377 }
378
379 class PacketFragmenterTest : public ::testing::Test {
380 protected:
381 void SetUp() override {
382 fragmenter = packet_fragmenter_get_interface();
383
384 packet_index = 0;
385 data_size_sum = 0;
386
387 callbacks.fragmented = fragmented_callback;
388 callbacks.reassembled = reassembled_callback;
389 reset_for(init);
390 fragmenter->init(&callbacks);
391 }
392
393 void TearDown() override { fragmenter->cleanup(); }
394
395 packet_fragmenter_callbacks_t callbacks;
396 };
397
398 TEST_F(PacketFragmenterTest, test_iso_fragment_necessary) {
399 reset_for(iso_fragmentation);
400 iso_has_ts = true;
401
402 BT_HDR* packet = manufacture_packet_for_fragmentation(MSG_STACK_TO_HC_HCI_ISO,
403 sample_data);
404 packet->event |= LOCAL_BLE_CONTROLLER_ID;
405 fragmenter->fragment_and_dispatch(packet, get_iso_data_size());
406
407 ASSERT_EQ(strlen(sample_data), data_size_sum);
408 }
409
410 TEST_F(PacketFragmenterTest, test_iso_no_fragment_necessary) {
411 reset_for(iso_no_fragmentation);
412 iso_has_ts = true;
413
414 BT_HDR* packet = manufacture_packet_for_fragmentation(MSG_STACK_TO_HC_HCI_ISO,
415 small_sample_data);
416 packet->event |= LOCAL_BLE_CONTROLLER_ID;
417 fragmenter->fragment_and_dispatch(packet, get_iso_data_size());
418
419 ASSERT_EQ(strlen(small_sample_data), data_size_sum);
420 }
421
422 TEST_F(PacketFragmenterTest, test_iso_fragment_necessary_no_ts) {
423 reset_for(iso_fragmentation);
424 iso_has_ts = false;
425 BT_HDR* packet = manufacture_packet_for_fragmentation(MSG_STACK_TO_HC_HCI_ISO,
426 sample_data);
427 packet->event |= LOCAL_BLE_CONTROLLER_ID;
428 fragmenter->fragment_and_dispatch(packet, get_iso_data_size());
429
430 ASSERT_EQ(strlen(sample_data), data_size_sum);
431 }
432
433 TEST_F(PacketFragmenterTest, test_iso_no_fragment_necessary_no_ts) {
434 reset_for(iso_no_fragmentation);
435 iso_has_ts = false;
436 BT_HDR* packet = manufacture_packet_for_fragmentation(MSG_STACK_TO_HC_HCI_ISO,
437 small_sample_data);
438 packet->event |= LOCAL_BLE_CONTROLLER_ID;
439 fragmenter->fragment_and_dispatch(packet, get_iso_data_size());
440
441 ASSERT_EQ(strlen(small_sample_data), data_size_sum);
442 }
443
444 TEST_F(PacketFragmenterTest, test_iso_no_reassembly_necessary) {
445 reset_for(iso_no_reassembly);
446 iso_has_ts = true;
447 manufacture_packet_and_then_reassemble(MSG_HC_TO_STACK_HCI_ISO, 50,
448 small_sample_data);
449
450 ASSERT_EQ(strlen(small_sample_data), data_size_sum);
451 EXPECT_CALL_COUNT(reassembled_callback, 1);
452 }
453
454 TEST_F(PacketFragmenterTest, test_iso_reassembly_necessary) {
455 reset_for(iso_reassembly);
456 iso_has_ts = true;
457 manufacture_packet_and_then_reassemble(MSG_HC_TO_STACK_HCI_ISO, 42,
458 sample_data);
459
460 ASSERT_EQ(strlen(sample_data), data_size_sum);
461 EXPECT_CALL_COUNT(reassembled_callback, 1);
462 }
463
464 TEST_F(PacketFragmenterTest, test_iso_no_reassembly_necessary_no_ts) {
465 reset_for(iso_no_reassembly);
466 iso_has_ts = false;
467 manufacture_packet_and_then_reassemble(MSG_HC_TO_STACK_HCI_ISO, (42 + 4),
468 small_sample_data);
469
470 ASSERT_EQ(strlen(small_sample_data), data_size_sum);
471 EXPECT_CALL_COUNT(reassembled_callback, 1);
472 }
473
474 TEST_F(PacketFragmenterTest, test_iso_reassembly_necessary_no_ts) {
475 reset_for(iso_reassembly);
476 iso_has_ts = false;
477 manufacture_packet_and_then_reassemble(MSG_HC_TO_STACK_HCI_ISO, 42,
478 sample_data);
479
480 ASSERT_EQ(strlen(sample_data), data_size_sum);
481 EXPECT_CALL_COUNT(reassembled_callback, 1);
482 }
483