1
2 // Copyright 2023 The Pigweed Authors
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 // use this file except in compliance with the License. You may obtain a copy of
6 // the License at
7 //
8 // https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 // License for the specific language governing permissions and limitations under
14 // the License.
15
16 #include "pw_bluetooth_sapphire/internal/host/sdp/pdu.h"
17
18 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
19 #include "pw_bluetooth_sapphire/internal/host/sdp/sdp.h"
20 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
21 #include "pw_unit_test/framework.h"
22
23 namespace bt::sdp {
24 namespace {
25
26 // The Default MTU in basic mode (Spec v5.1, Vol 3 Part A Section 5.1)
27 const uint16_t kDefaultMaxSize = 672;
28 // The smallest MTU allowed by the spec.
29 const uint16_t kMinMaxSize = 48;
30
31 // Helper function to match one of two options, and print useful information on
32 // failure.
33 template <class Container1, class Container2, class Container3>
MatchesOneOf(const Container1 & one,const Container2 & two,const Container3 & actual)34 bool MatchesOneOf(const Container1& one,
35 const Container2& two,
36 const Container3& actual) {
37 bool opt_one =
38 std::equal(one.begin(), one.end(), actual.begin(), actual.end());
39 bool opt_two =
40 std::equal(two.begin(), two.end(), actual.begin(), actual.end());
41
42 if (!(opt_one || opt_two)) {
43 std::cout << "Expected one of {";
44 PrintByteContainer(one.begin(), one.end());
45 std::cout << "}\n or {";
46 PrintByteContainer(two.begin(), two.end());
47 std::cout << "}\n Found: { ";
48 PrintByteContainer(actual.begin(), actual.end());
49 std::cout << "}" << std::endl;
50 }
51 return opt_one || opt_two;
52 }
53
TEST(PDUTest,ErrorResponse)54 TEST(PDUTest, ErrorResponse) {
55 ErrorResponse response;
56 EXPECT_FALSE(response.complete());
57 EXPECT_EQ(nullptr,
58 response.GetPDU(0xF00F /* ignored */,
59 0xDEAD,
60 kDefaultMaxSize /* ignored */,
61 BufferView()));
62
63 StaticByteBuffer kInvalidContState(
64 0x01, // opcode: kErrorResponse
65 0xDE,
66 0xAD, // transaction ID: 0xDEAD
67 0x00,
68 0x02, // parameter length: 2 bytes
69 0x00,
70 0x05, // ErrorCode: Invalid Continuation State
71 0xFF,
72 0x00 // extra bytes to cause an error
73 );
74
75 fit::result<Error<>> status =
76 response.Parse(kInvalidContState.view(sizeof(Header)));
77 EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
78
79 status = response.Parse(kInvalidContState.view(sizeof(Header), 2));
80 EXPECT_EQ(fit::ok(), status);
81 EXPECT_TRUE(response.complete());
82 EXPECT_EQ(ErrorCode::kInvalidContinuationState, response.error_code());
83
84 response.set_error_code(ErrorCode::kInvalidContinuationState);
85 auto ptr = response.GetPDU(0xF00F /* ignored */,
86 0xDEAD,
87 kDefaultMaxSize /* ignored */,
88 BufferView());
89
90 ASSERT_TRUE(ptr);
91 EXPECT_TRUE(ContainersEqual(kInvalidContState.view(0, 7), *ptr));
92 }
93
TEST(PDUTest,ServiceSearchRequestParse)94 TEST(PDUTest, ServiceSearchRequestParse) {
95 const StaticByteBuffer kL2capSearch(
96 // ServiceSearchPattern
97 0x35,
98 0x03, // Sequence uint8 3 bytes
99 0x19,
100 0x01,
101 0x00, // UUID: Protocol: L2CAP
102 0x00,
103 0x10, // MaximumServiceRecordCount: 16
104 0x00 // Continuation State: none
105 );
106
107 ServiceSearchRequest req(kL2capSearch);
108 EXPECT_TRUE(req.valid());
109 EXPECT_EQ(1u, req.service_search_pattern().size());
110 EXPECT_TRUE(req.service_search_pattern().count(protocol::kL2CAP));
111 EXPECT_EQ(16, req.max_service_record_count());
112
113 const StaticByteBuffer kL2capSearchOne(
114 // ServiceSearchPattern
115 0x35,
116 0x06, // Sequence uint8 6 bytes
117 0x19,
118 0x01,
119 0x00, // UUID: Protocol: L2CAP
120 0x19,
121 0xED,
122 0xFE, // UUID: 0xEDFE (unknown, doesn't need to be found)
123 0x00,
124 0x01, // MaximumServiceRecordCount: 1
125 0x00 // Continuation State: none
126 );
127
128 ServiceSearchRequest req_one(kL2capSearchOne);
129 EXPECT_TRUE(req_one.valid());
130 EXPECT_EQ(2u, req_one.service_search_pattern().size());
131 EXPECT_EQ(1, req_one.max_service_record_count());
132
133 const StaticByteBuffer kInvalidNoItems(
134 // ServiceSearchPattern
135 0x35,
136 0x00, // Sequence uint8 0 bytes
137 0xFF,
138 0xFF, // MaximumServiceRecordCount: (none)
139 0x00 // Continuation State: none
140 );
141
142 ServiceSearchRequest req2(kInvalidNoItems);
143 EXPECT_FALSE(req2.valid());
144
145 const StaticByteBuffer kInvalidTooManyItems(
146 // ServiceSearchPattern
147 0x35,
148 0x27, // Sequence uint8 27 bytes
149 0x19,
150 0x30,
151 0x01, // 13 UUIDs in the search
152 0x19,
153 0x30,
154 0x02,
155 0x19,
156 0x30,
157 0x03,
158 0x19,
159 0x30,
160 0x04,
161 0x19,
162 0x30,
163 0x05,
164 0x19,
165 0x30,
166 0x06,
167 0x19,
168 0x30,
169 0x07,
170 0x19,
171 0x30,
172 0x08,
173 0x19,
174 0x30,
175 0x09,
176 0x19,
177 0x30,
178 0x10,
179 0x19,
180 0x30,
181 0x11,
182 0x19,
183 0x30,
184 0x12,
185 0x19,
186 0x30,
187 0x13,
188 0xFF,
189 0xFF, // MaximumServiceRecordCount: (none)
190 0x00 // Continuation State: none
191 );
192
193 ServiceSearchRequest req3(kInvalidTooManyItems);
194 EXPECT_FALSE(req3.valid());
195
196 const StaticByteBuffer kInvalidMaxSizeZero(
197 // ServiceSearchPattern
198 0x35,
199 0x06, // Sequence uint8 6 bytes
200 0x19,
201 0x01,
202 0x00, // UUID: Protocol: L2CAP
203 0x19,
204 0xED,
205 0xFE, // UUID: 0xEDFE (unknown, doesn't need to be found)
206 0x00,
207 0x00, // MaximumServiceRecordCount: 0
208 0x00 // Continuation State: none
209 );
210
211 ServiceSearchRequest req4(kInvalidMaxSizeZero);
212 EXPECT_FALSE(req4.valid());
213 }
214
TEST(PDUTest,ServiceSearchRequestGetPDU)215 TEST(PDUTest, ServiceSearchRequestGetPDU) {
216 ServiceSearchRequest req;
217
218 req.set_search_pattern({protocol::kATT, protocol::kL2CAP});
219 req.set_max_service_record_count(64);
220
221 // Order is not specified, so there are two valid PDUs representing this.
222 const StaticByteBuffer kExpected(kServiceSearchRequest,
223 0x12,
224 0x34, // Transaction ID
225 0x00,
226 0x0B, // Parameter length (11 bytes)
227 // ServiceSearchPattern
228 0x35,
229 0x06, // Sequence uint8 6 bytes
230 0x19,
231 0x00,
232 0x07, // UUID (ATT)
233 0x19,
234 0x01,
235 0x00, // UUID (L2CAP)
236 0x00,
237 0x40, // MaximumServiceRecordCount: 64
238 0x00 // No continuation state
239 );
240 const auto kExpected2 =
241 StaticByteBuffer(kServiceSearchRequest,
242 0x12,
243 0x34, // Transaction ID
244 0x00,
245 0x0B, // Parameter length (11 bytes)
246 // ServiceSearchPattern
247 0x35,
248 0x06, // Sequence uint8 6 bytes
249 0x19,
250 0x01,
251 0x00, // UUID (L2CAP)
252 0x19,
253 0x00,
254 0x07, // UUID (ATT)
255 0x00,
256 0x40, // MaximumServiceRecordCount: 64
257 0x00 // No continuation state
258 );
259
260 auto pdu = req.GetPDU(0x1234);
261 EXPECT_TRUE(MatchesOneOf(kExpected, kExpected2, *pdu));
262 }
263
TEST(PDUTest,ServiceSearchResponseParse)264 TEST(PDUTest, ServiceSearchResponseParse) {
265 const StaticByteBuffer kValidResponse(
266 0x00,
267 0x02, // Total service record count: 2
268 0x00,
269 0x02, // Current service record count: 2
270 0x00,
271 0x00,
272 0x00,
273 0x01, // Service Handle 1
274 0x00,
275 0x00,
276 0x00,
277 0x02, // Service Handle 2
278 0x00 // No continuation state
279 );
280
281 ServiceSearchResponse resp;
282 auto status = resp.Parse(kValidResponse);
283 EXPECT_EQ(fit::ok(), status);
284
285 // Can't parse into an already complete record.
286 status = resp.Parse(kValidResponse);
287 EXPECT_TRUE(status.is_error());
288
289 const auto kNotEnoughRecords =
290 StaticByteBuffer(0x00,
291 0x02, // Total service record count: 2
292 0x00,
293 0x02, // Current service record count: 2
294 0x00,
295 0x00,
296 0x00,
297 0x01, // Service Handle 1
298 0x00 // No continuation state
299 );
300 // Doesn't contain the right # of records.
301 ServiceSearchResponse resp2;
302 status = resp2.Parse(kNotEnoughRecords);
303 EXPECT_TRUE(status.is_error());
304
305 // A Truncated packet doesn't parse either.
306 const StaticByteBuffer kTruncated(0x00,
307 0x02, // Total service record count: 2
308 0x00,
309 0x02 // Current service record count: 2
310 );
311 ServiceSearchResponse resp3;
312 status = resp3.Parse(kTruncated);
313 EXPECT_TRUE(status.is_error());
314
315 // Too many bytes for the number of records is also not allowed (with or
316 // without a continuation state)
317 const StaticByteBuffer kTooLong(0x00,
318 0x01, // Total service record count: 1
319 0x00,
320 0x01, // Current service record count: 1
321 0x00,
322 0x00,
323 0x00,
324 0x01, // Service Handle 1
325 0x00,
326 0x00,
327 0x00,
328 0x02, // Service Handle 2
329 0x00 // No continuation state
330 );
331 ServiceSearchResponse resp4;
332 status = resp4.Parse(kTooLong);
333 EXPECT_TRUE(status.is_error());
334
335 const auto kTooLongWithContinuation =
336 StaticByteBuffer(0x00,
337 0x04, // Total service record count: 1
338 0x00,
339 0x01, // Current service record count: 1
340 0x00,
341 0x00,
342 0x00,
343 0x01, // Service Handle 1
344 0x00,
345 0x00,
346 0x00,
347 0x02, // Service Handle 2
348 0x04, // Continuation state (len: 4)
349 0xF0,
350 0x9F,
351 0x92,
352 0x96 // Continuation state
353 );
354 ServiceSearchResponse resp5;
355 status = resp5.Parse(kTooLongWithContinuation);
356 EXPECT_TRUE(status.is_error());
357 }
358
TEST(PDUTest,ServiceSearchResponsePDU)359 TEST(PDUTest, ServiceSearchResponsePDU) {
360 std::vector<ServiceHandle> results{1, 2};
361 ServiceSearchResponse resp;
362
363 // Empty results
364 const StaticByteBuffer kExpectedEmpty(
365 0x03, // ServiceSearch Response PDU ID
366 0x01,
367 0x10, // Transaction ID (0x0110)
368 0x00,
369 0x05, // Parameter length: 5 bytes
370 0x00,
371 0x00, // Total service record count: 0
372 0x00,
373 0x00, // Current service record count: 0
374 0x00 // No continuation state
375 );
376
377 auto pdu = resp.GetPDU(0xFFFF, 0x0110, kDefaultMaxSize, BufferView());
378 EXPECT_TRUE(ContainersEqual(kExpectedEmpty, *pdu));
379
380 resp.set_service_record_handle_list(results);
381
382 const StaticByteBuffer kExpected(0x03, // ServiceSearch Response PDU ID
383 0x01,
384 0x10, // Transaction ID (0x0110)
385 0x00,
386 0x0d, // Parameter length: 13 bytes
387 0x00,
388 0x02, // Total service record count: 2
389 0x00,
390 0x02, // Current service record count: 2
391 0x00,
392 0x00,
393 0x00,
394 0x01, // Service record 1
395 0x00,
396 0x00,
397 0x00,
398 0x02, // Service record 2
399 0x00 // No continuation state
400 );
401
402 pdu = resp.GetPDU(0xFFFF, 0x0110, kDefaultMaxSize, BufferView());
403 EXPECT_TRUE(ContainersEqual(kExpected, *pdu));
404
405 const auto kExpectedLimited =
406 StaticByteBuffer(0x03, // ServiceSearchResponse PDU ID
407 0x01,
408 0x10, // Transaction ID (0x0110)
409 0x00,
410 0x09, // Parameter length: 9
411 0x00,
412 0x01, // Total service record count: 1
413 0x00,
414 0x01, // Current service record count: 1
415 0x00,
416 0x00,
417 0x00,
418 0x01, // Service record 1
419 0x00 // No continuation state
420 );
421
422 pdu = resp.GetPDU(1, 0x0110, kDefaultMaxSize, BufferView());
423 EXPECT_TRUE(ContainersEqual(kExpectedLimited, *pdu));
424
425 resp.set_service_record_handle_list({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
426 const auto kExpectedLarge =
427 StaticByteBuffer(0x03, // ServiceSearchResponse PDU ID
428 0x01,
429 0x10, // Transaction ID (0x0110)
430 0x00,
431 0x31, // Parameter length: 49
432 0x00,
433 0x0B, // Total service record count: 11
434 0x00,
435 0x0B, // Current service record count: 11
436 0x00,
437 0x00,
438 0x00,
439 0x01, // Service record 1
440 0x00,
441 0x00,
442 0x00,
443 0x02, // Service record 2
444 0x00,
445 0x00,
446 0x00,
447 0x03, // Service record 3
448 0x00,
449 0x00,
450 0x00,
451 0x04, // Service record 4
452 0x00,
453 0x00,
454 0x00,
455 0x05, // Service record 5
456 0x00,
457 0x00,
458 0x00,
459 0x06, // Service record 6
460 0x00,
461 0x00,
462 0x00,
463 0x07, // Service record 7
464 0x00,
465 0x00,
466 0x00,
467 0x08, // Service record 8
468 0x00,
469 0x00,
470 0x00,
471 0x09, // Service record 9
472 0x00,
473 0x00,
474 0x00,
475 0x0A, // Service record 10
476 0x00,
477 0x00,
478 0x00,
479 0x0B, // Service record 11
480 0x00 // No continuation state.
481 );
482
483 pdu = resp.GetPDU(0x00FF, 0x0110, kDefaultMaxSize, BufferView());
484 EXPECT_TRUE(ContainersEqual(kExpectedLarge, *pdu));
485 }
486
TEST(PDUTest,ServiceSearchResponsePDU_MaxSize)487 TEST(PDUTest, ServiceSearchResponsePDU_MaxSize) {
488 std::vector<ServiceHandle> results{1, 2};
489 ServiceSearchResponse resp;
490
491 // Empty results
492 const StaticByteBuffer kExpectedEmpty(
493 0x03, // ServiceSearch Response PDU ID
494 0x01,
495 0x10, // Transaction ID (0x0110)
496 0x00,
497 0x05, // Parameter length: 5 bytes
498 0x00,
499 0x00, // Total service record count: 0
500 0x00,
501 0x00, // Current service record count: 0
502 0x00 // No continuation state
503 );
504
505 auto pdu = resp.GetPDU(0xFFFF, 0x0110, kMinMaxSize, BufferView());
506 EXPECT_TRUE(ContainersEqual(kExpectedEmpty, *pdu));
507
508 resp.set_service_record_handle_list(results);
509
510 const StaticByteBuffer kExpected(0x03, // ServiceSearch Response PDU ID
511 0x01,
512 0x10, // Transaction ID (0x0110)
513 0x00,
514 0x0d, // Parameter length: 13 bytes
515 0x00,
516 0x02, // Total service record count: 2
517 0x00,
518 0x02, // Current service record count: 2
519 0x00,
520 0x00,
521 0x00,
522 0x01, // Service record 1
523 0x00,
524 0x00,
525 0x00,
526 0x02, // Service record 2
527 0x00 // No continuation state
528 );
529
530 pdu = resp.GetPDU(0xFFFF, 0x0110, kMinMaxSize, BufferView());
531 EXPECT_TRUE(ContainersEqual(kExpected, *pdu));
532
533 const auto kExpectedLimited =
534 StaticByteBuffer(0x03, // ServiceSearchResponse PDU ID
535 0x01,
536 0x10, // Transaction ID (0x0110)
537 0x00,
538 0x09, // Parameter length: 9
539 0x00,
540 0x01, // Total service record count: 1
541 0x00,
542 0x01, // Current service record count: 1
543 0x00,
544 0x00,
545 0x00,
546 0x01, // Service record 1
547 0x00 // No continuation state
548 );
549
550 pdu = resp.GetPDU(1, 0x0110, kMinMaxSize, BufferView());
551 EXPECT_TRUE(ContainersEqual(kExpectedLimited, *pdu));
552
553 resp.set_service_record_handle_list({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
554 const auto kExpectedContinuation =
555 StaticByteBuffer(0x03, // ServiceSearchResponse PDU ID
556 0x01,
557 0x10, // Transaction ID (0x0110)
558 0x00,
559 0x2B, // Parameter length: 42
560 0x00,
561 0x0B, // Total service record count: 11
562 0x00,
563 0x09, // Current service record count: 9
564 0x00,
565 0x00,
566 0x00,
567 0x01, // Service record 1
568 0x00,
569 0x00,
570 0x00,
571 0x02, // Service record 2
572 0x00,
573 0x00,
574 0x00,
575 0x03, // Service record 3
576 0x00,
577 0x00,
578 0x00,
579 0x04, // Service record 4
580 0x00,
581 0x00,
582 0x00,
583 0x05, // Service record 5
584 0x00,
585 0x00,
586 0x00,
587 0x06, // Service record 6
588 0x00,
589 0x00,
590 0x00,
591 0x07, // Service record 7
592 0x00,
593 0x00,
594 0x00,
595 0x08, // Service record 8
596 0x00,
597 0x00,
598 0x00,
599 0x09, // Service record 9
600 0x02,
601 0x00,
602 0x09 // Continuation state.
603 );
604
605 // The MTU size here should limit the number of service records returned to 9.
606 pdu = resp.GetPDU(0x00FF, 0x0110, kMinMaxSize, BufferView());
607 EXPECT_TRUE(ContainersEqual(kExpectedContinuation, *pdu));
608
609 const StaticByteBuffer kExpectedRest(0x03, // ServiceSearchResponse PDU ID
610 0x01,
611 0x10, // Transaction ID (0x0110)
612 0x00,
613 0x0D, // Parameter length: 13
614 0x00,
615 0x0B, // Total service record count: 11
616 0x00,
617 0x02, // Current service record count: 2
618 0x00,
619 0x00,
620 0x00,
621 0x0A, // Service record 10
622 0x00,
623 0x00,
624 0x00,
625 0x0B, // Service record 11
626 0x00 // No continuation state.
627 );
628
629 pdu = resp.GetPDU(0x00FF, 0x0110, kMinMaxSize, StaticByteBuffer(0x00, 0x09));
630 EXPECT_TRUE(ContainersEqual(kExpectedRest, *pdu));
631 }
632
TEST(PDUTest,ServiceAttributeRequestValidity)633 TEST(PDUTest, ServiceAttributeRequestValidity) {
634 ServiceAttributeRequest req;
635
636 // No attributes requested, so it begins invalid
637 EXPECT_FALSE(req.valid());
638
639 // Adding an attribute makes it valid, and adds a range.
640 req.AddAttribute(kServiceClassIdList);
641
642 EXPECT_TRUE(req.valid());
643 EXPECT_EQ(1u, req.attribute_ranges().size());
644 EXPECT_EQ(kServiceClassIdList, req.attribute_ranges().front().start);
645
646 // Adding an attribute adjacent just adds to the range (on either end)
647 req.AddAttribute(kServiceClassIdList - 1); // kServiceRecordHandle
648 req.AddAttribute(kServiceClassIdList + 1);
649 req.AddAttribute(kServiceClassIdList + 2);
650
651 EXPECT_TRUE(req.valid());
652 EXPECT_EQ(1u, req.attribute_ranges().size());
653 EXPECT_EQ(kServiceClassIdList - 1, req.attribute_ranges().front().start);
654 EXPECT_EQ(kServiceClassIdList + 2, req.attribute_ranges().front().end);
655
656 // Adding a disjoint range makes it two ranges, and they're in the right
657 // order.
658 req.AddAttribute(kServiceClassIdList + 4);
659
660 EXPECT_TRUE(req.valid());
661 EXPECT_EQ(2u, req.attribute_ranges().size());
662 EXPECT_EQ(kServiceClassIdList - 1, req.attribute_ranges().front().start);
663 EXPECT_EQ(kServiceClassIdList + 2, req.attribute_ranges().front().end);
664 EXPECT_EQ(kServiceClassIdList + 4, req.attribute_ranges().back().start);
665 EXPECT_EQ(kServiceClassIdList + 4, req.attribute_ranges().back().end);
666
667 // Adding one that makes it contiguous collapses them to a single range.
668 req.AddAttribute(kServiceClassIdList + 3);
669
670 EXPECT_EQ(1u, req.attribute_ranges().size());
671 EXPECT_EQ(kServiceClassIdList - 1, req.attribute_ranges().front().start);
672 EXPECT_EQ(kServiceClassIdList + 4, req.attribute_ranges().front().end);
673
674 EXPECT_TRUE(req.valid());
675 }
676
TEST(PDUTest,ServiceAttributeRequestAddRange)677 TEST(PDUTest, ServiceAttributeRequestAddRange) {
678 ServiceAttributeRequest req;
679
680 req.AddAttributeRange(0x0010, 0xFFF0);
681
682 EXPECT_EQ(1u, req.attribute_ranges().size());
683 EXPECT_EQ(0x0010, req.attribute_ranges().front().start);
684 EXPECT_EQ(0xFFF0, req.attribute_ranges().front().end);
685
686 req.AddAttributeRange(0x0100, 0xFF00);
687
688 EXPECT_EQ(1u, req.attribute_ranges().size());
689 EXPECT_EQ(0x0010, req.attribute_ranges().front().start);
690 EXPECT_EQ(0xFFF0, req.attribute_ranges().front().end);
691
692 req.AddAttributeRange(0x0000, 0x0002);
693
694 EXPECT_EQ(2u, req.attribute_ranges().size());
695 EXPECT_EQ(0x0000, req.attribute_ranges().front().start);
696 EXPECT_EQ(0x0002, req.attribute_ranges().front().end);
697
698 req.AddAttributeRange(0x0003, 0x000F);
699
700 EXPECT_EQ(1u, req.attribute_ranges().size());
701 EXPECT_EQ(0x0000, req.attribute_ranges().front().start);
702 EXPECT_EQ(0xFFF0, req.attribute_ranges().front().end);
703
704 req.AddAttributeRange(0xFFF2, 0xFFF3);
705 req.AddAttributeRange(0xFFF5, 0xFFF6);
706 req.AddAttributeRange(0xFFF8, 0xFFF9);
707 req.AddAttributeRange(0xFFFB, 0xFFFC);
708
709 EXPECT_EQ(5u, req.attribute_ranges().size());
710
711 // merges 0x0000-0xFFF0 with 0xFFF2-0xFFF3 and new range leaving
712 // 0x0000-0xFFF3, 0xFFF5-0xFFF6, 0xFFF8-0xFFF9 and 0xFFFB-0xFFFC
713 req.AddAttributeRange(0xFFF1, 0xFFF1);
714
715 EXPECT_EQ(4u, req.attribute_ranges().size());
716
717 // merges everything except 0xFFFB-0xFFFC
718 req.AddAttributeRange(0xFFF1, 0xFFF9);
719
720 EXPECT_EQ(2u, req.attribute_ranges().size());
721
722 req.AddAttributeRange(0xFFFA, 0xFFFF);
723
724 EXPECT_EQ(1u, req.attribute_ranges().size());
725 EXPECT_EQ(0x0000, req.attribute_ranges().front().start);
726 EXPECT_EQ(0xFFFF, req.attribute_ranges().front().end);
727 }
728
TEST(PDUTest,ServiceAttributeRequestParse)729 TEST(PDUTest, ServiceAttributeRequestParse) {
730 const StaticByteBuffer kSDPAllAttributes(
731 0x00,
732 0x00,
733 0x00,
734 0x00, // ServiceRecordHandle: 0
735 0xF0,
736 0x0F, // Maximum attribute byte count: (max = 61455)
737 // Attribute ID List
738 0x35,
739 0x05, // Sequence uint8 5 bytes
740 0x0A, // uint32_t
741 0x00,
742 0x00,
743 0xFF,
744 0xFF, // Attribute range: 0x000 - 0xFFFF (All of them)
745 0x00 // No continuation state
746 );
747
748 ServiceAttributeRequest req(kSDPAllAttributes);
749
750 EXPECT_TRUE(req.valid());
751 EXPECT_EQ(1u, req.attribute_ranges().size());
752 EXPECT_EQ(0x0000, req.attribute_ranges().front().start);
753 EXPECT_EQ(0xFFFF, req.attribute_ranges().front().end);
754 EXPECT_EQ(61455, req.max_attribute_byte_count());
755
756 const auto kContinued =
757 StaticByteBuffer(0x00,
758 0x00,
759 0x00,
760 0x00, // ServiceRecordHandle: 0
761 0x00,
762 0x0F, // Maximum attribute byte count: (max = 15)
763 // Attribute ID List
764 0x35,
765 0x06, // Sequence uint8 3 bytes
766 0x09, // uint16_t
767 0x00,
768 0x01, // Attribute ID: 1
769 0x09, // uint16_t
770 0x00,
771 0x02, // Attribute ID: 2
772 0x03,
773 0x12,
774 0x34,
775 0x56 // Continuation state
776 );
777
778 ServiceAttributeRequest req_cont_state(kContinued);
779
780 EXPECT_TRUE(req_cont_state.valid());
781 EXPECT_EQ(2u, req_cont_state.attribute_ranges().size());
782 EXPECT_EQ(0x0001, req_cont_state.attribute_ranges().front().start);
783 EXPECT_EQ(0x0001, req_cont_state.attribute_ranges().front().end);
784 EXPECT_EQ(0x0002, req_cont_state.attribute_ranges().back().start);
785 EXPECT_EQ(0x0002, req_cont_state.attribute_ranges().back().end);
786 EXPECT_EQ(15, req_cont_state.max_attribute_byte_count());
787
788 // Too short request.
789 ServiceAttributeRequest req_short((BufferView()));
790
791 EXPECT_FALSE(req_short.valid());
792
793 const auto kInvalidMaxBytes =
794 StaticByteBuffer(0x00,
795 0x00,
796 0x00,
797 0x00, // ServiceRecordHandle: 0
798 0x00,
799 0x04, // Maximum attribute byte count (4)
800 // Attribute ID List
801 0x35,
802 0x03, // Sequence uint8 3 bytes
803 0x09,
804 0x00,
805 0x02, // uint16_t (2)
806 0x00 // No continuation state
807 );
808
809 ServiceAttributeRequest req_minmax(kInvalidMaxBytes);
810
811 EXPECT_FALSE(req_minmax.valid());
812
813 // Invalid order of the attributes.
814 const auto kInvalidAttributeListOrder =
815 StaticByteBuffer(0x00,
816 0x00,
817 0x00,
818 0x00, // ServiceRecordHandle: 0
819 0xFF,
820 0xFF, // Maximum attribute byte count: (max = 65535)
821 // Attribute ID List
822 0x35,
823 0x06, // Sequence uint8 6 bytes
824 0x09,
825 0x00,
826 0x02, // uint16_t (2)
827 0x09,
828 0x00,
829 0x01, // uint16_t (1)
830 0x00 // No continuation state
831 );
832
833 ServiceAttributeRequest req_order(kInvalidAttributeListOrder);
834
835 EXPECT_FALSE(req_short.valid());
836
837 // AttributeID List has invalid items
838 const auto kInvalidAttributeList =
839 StaticByteBuffer(0x00,
840 0x00,
841 0x00,
842 0x00, // ServiceRecordHandle: 0
843 0xFF,
844 0xFF, // Maximum attribute byte count: (max = 65535)
845 // Attribute ID List
846 0x35,
847 0x06, // Sequence uint8 5 bytes
848 0x09,
849 0x00,
850 0x02, // uint16_t (2)
851 0x19,
852 0x00,
853 0x01, // UUID (0x0001)
854 0x00 // No continuation state
855 );
856
857 ServiceAttributeRequest req_baditems(kInvalidAttributeList);
858
859 EXPECT_FALSE(req_baditems.valid());
860
861 // AttributeID list is empty
862 const auto kInvalidNoItems =
863 StaticByteBuffer(0x00,
864 0x00,
865 0x00,
866 0x00, // ServiceRecordHandle: 0
867 0xFF,
868 0xFF, // Maximum attribute byte count: max
869 0x35,
870 0x00, // Sequence uint8 no bytes
871 0x00 // No continuation state
872 );
873
874 ServiceAttributeRequest req_noitems(kInvalidNoItems);
875 EXPECT_FALSE(req_noitems.valid());
876 }
877
TEST(PDUTest,ServiceAttributeRequestGetPDU)878 TEST(PDUTest, ServiceAttributeRequestGetPDU) {
879 ServiceAttributeRequest req;
880 req.AddAttribute(0xF00F);
881 req.AddAttributeRange(0x0001, 0xBECA);
882
883 req.set_service_record_handle(0xEFFECACE);
884 req.set_max_attribute_byte_count(32);
885
886 const auto kExpected =
887 StaticByteBuffer(kServiceAttributeRequest,
888 0x12,
889 0x34, // transaction id
890 0x00,
891 0x11, // Parameter Length (17 bytes)
892 0xEF,
893 0xFE,
894 0xCA,
895 0xCE, // ServiceRecordHandle (0xEFFECACE)
896 0x00,
897 0x20, // MaxAttributeByteCount (32)
898 // Attribute ID list
899 0x35,
900 0x08, // Sequence uint8 8 bytes
901 0x0A,
902 0x00,
903 0x01,
904 0xBE,
905 0xCA, // uint32_t (0x0001BECA)
906 0x09,
907 0xF0,
908 0x0F, // uint16_t (0xF00F)
909 0x00 // No continuation state
910 );
911
912 auto pdu = req.GetPDU(0x1234);
913 EXPECT_TRUE(ContainersEqual(kExpected, *pdu));
914 }
915
TEST(PDUTest,ServiceAttributeRequestGetPDUFailsTooManyAttributes)916 TEST(PDUTest, ServiceAttributeRequestGetPDUFailsTooManyAttributes) {
917 ServiceAttributeRequest req;
918 // Skip attributes to prevent them from being combined into a range.
919 for (AttributeId attr = 0x0000; attr <= kMaxAttributeRangesInRequest * 2;
920 attr += 2) {
921 req.AddAttribute(attr);
922 }
923
924 req.set_service_record_handle(0xEFFECACE);
925 req.set_max_attribute_byte_count(32);
926
927 EXPECT_EQ(req.GetPDU(0x1234), nullptr);
928 }
929
TEST(PDUTest,ServiceAttributeResponseParse)930 TEST(PDUTest, ServiceAttributeResponseParse) {
931 const StaticByteBuffer kValidResponseEmpty(0x00,
932 0x02, // AttributeListByteCount (2
933 // bytes) Attribute List
934 0x35,
935 0x00, // Sequence uint8 0 bytes
936 0x00 // No continuation state
937 );
938
939 ServiceAttributeResponse resp;
940 auto status = resp.Parse(kValidResponseEmpty);
941
942 EXPECT_EQ(fit::ok(), status);
943
944 const StaticByteBuffer kValidResponseItems(
945 0x00,
946 0x12, // AttributeListByteCount (18 bytes)
947 // Attribute List
948 0x35,
949 0x10, // Sequence uint8 16 bytes
950 0x09,
951 0x00,
952 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
953 0x0A,
954 0xFE,
955 0xED,
956 0xBE,
957 0xEF, // Element: uint32_t (0xFEEDBEEF)
958 0x09,
959 0x00,
960 0x01, // Handle: uint16_t (1 = kServiceClassIdList)
961 0x35,
962 0x03,
963 0x19,
964 0x11,
965 0x01, // Element: Sequence (3) { UUID(0x1101) }
966 0x00 // No continuation state
967 );
968
969 ServiceAttributeResponse resp2;
970 status = resp2.Parse(kValidResponseItems);
971
972 EXPECT_EQ(fit::ok(), status);
973 EXPECT_EQ(2u, resp2.attributes().size());
974 auto it = resp2.attributes().find(0x00);
975 EXPECT_NE(resp2.attributes().end(), it);
976 EXPECT_EQ(DataElement::Type::kUnsignedInt, it->second.type());
977
978 it = resp2.attributes().find(0x01);
979 EXPECT_NE(resp2.attributes().end(), it);
980 EXPECT_EQ(DataElement::Type::kSequence, it->second.type());
981
982 const StaticByteBuffer kInvalidItemsWrongOrder(
983 0x00,
984 0x12, // AttributeListByteCount (18 bytes)
985 // Attribute List
986 0x35,
987 0x10, // Sequence uint8 16 bytes
988 0x09,
989 0x00,
990 0x01, // Handle: uint16_t (1 = kServiceClassIdList)
991 0x35,
992 0x03,
993 0x19,
994 0x11,
995 0x01, // Element: Sequence (3) { UUID(0x1101) }
996 0x09,
997 0x00,
998 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
999 0x0A,
1000 0xFE,
1001 0xED,
1002 0xBE,
1003 0xEF, // Element: uint32_t (0xFEEDBEEF)
1004 0x00 // No continuation state
1005 );
1006
1007 ServiceAttributeResponse resp3;
1008 status = resp3.Parse(kInvalidItemsWrongOrder);
1009
1010 EXPECT_TRUE(status.is_error());
1011
1012 const StaticByteBuffer kInvalidHandleWrongType(
1013 0x00,
1014 0x11, // AttributeListByteCount (17 bytes)
1015 // Attribute List
1016 0x35,
1017 0x0F, // Sequence uint8 15 bytes
1018 0x09,
1019 0x00,
1020 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
1021 0x0A,
1022 0xFE,
1023 0xED,
1024 0xBE,
1025 0xEF, // Element: uint32_t (0xFEEDBEEF)
1026 0x08,
1027 0x01, // Handle: uint8_t (!) (1 = kServiceClassIdList)
1028 0x35,
1029 0x03,
1030 0x19,
1031 0x11,
1032 0x01, // Element: Sequence (3) { UUID(0x1101) }
1033 0x00 // No continuation state
1034 );
1035
1036 ServiceAttributeResponse resp_wrongtype;
1037 status = resp_wrongtype.Parse(kInvalidHandleWrongType);
1038
1039 EXPECT_TRUE(status.is_error());
1040
1041 const StaticByteBuffer kInvalidByteCount(
1042 0x00,
1043 0x12, // AttributeListByteCount (18 bytes)
1044 // Attribute List (only 17 bytes long)
1045 0x35,
1046 0x0F, // Sequence uint8 15 bytes
1047 0x09,
1048 0x00,
1049 0x01, // Handle: uint16_t (1)
1050 0x35,
1051 0x03,
1052 0x19,
1053 0x11,
1054 0x01, // Element: Sequence (3) { UUID(0x1101) }
1055 0x09,
1056 0x00,
1057 0x00, // Handle: uint16_t (0)
1058 0x25,
1059 0x02,
1060 'h',
1061 'i', // Element: String ('hi')
1062 0x00 // No continuation state
1063 );
1064
1065 ServiceAttributeResponse resp4;
1066 status = resp4.Parse(kInvalidByteCount);
1067 EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
1068
1069 // Sending too much data eventually fails.
1070 auto kContinuationPacket = DynamicByteBuffer(4096);
1071 // Put the correct byte count at the front: 4096 - 2 (byte count) - 5
1072 // (continuation size)
1073 const StaticByteBuffer kAttributeListByteCount(0x0F, 0xF9);
1074 kContinuationPacket.Write(kAttributeListByteCount, 0);
1075 // Put the correct continuation at the end.
1076 const StaticByteBuffer kContinuation(0x04, 0xF0, 0x9F, 0x92, 0x96);
1077 kContinuationPacket.Write(kContinuation, kContinuationPacket.size() - 5);
1078
1079 ServiceAttributeResponse resp5;
1080 status = resp5.Parse(kContinuationPacket);
1081 EXPECT_EQ(ToResult(HostError::kInProgress), status);
1082 while (status == ToResult(HostError::kInProgress)) {
1083 status = resp5.Parse(kContinuationPacket);
1084 }
1085 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
1086 }
1087
TEST(PDUTest,ServiceAttributeResponseGetPDU_MaxSize)1088 TEST(PDUTest, ServiceAttributeResponseGetPDU_MaxSize) {
1089 ServiceAttributeResponse resp;
1090
1091 // Even if set in the wrong order, attributes should be sorted in the PDU.
1092 resp.set_attribute(0x4000, DataElement(uint16_t{0xfeed}));
1093 resp.set_attribute(0x4001, DataElement(protocol::kSDP));
1094 resp.set_attribute(0x4002, DataElement(uint32_t{0xc0decade}));
1095 DataElement str;
1096 str.Set(std::string(""));
1097 resp.set_attribute(0x4003, std::move(str));
1098 resp.set_attribute(0x4005, DataElement(uint32_t{0xC0DEB4BE}));
1099 resp.set_attribute(kServiceRecordHandle, DataElement(uint32_t{0}));
1100
1101 const uint16_t kTransactionID = 0xfeed;
1102
1103 const StaticByteBuffer kExpectedContinuation(
1104 0x05, // ServiceAttributeResponse
1105 UpperBits(kTransactionID),
1106 LowerBits(kTransactionID), // Transaction ID
1107 0x00,
1108 0x2B, // Param Length (43 bytes)
1109 0x00,
1110 0x24, // AttributeListsByteCount (36 bytes)
1111 // AttributeLists
1112 0x35,
1113 0x2d, // Sequence uint8 46 bytes
1114 0x09,
1115 0x00,
1116 0x00, // uint16_t (handle) = kServiceRecordHandle
1117 0x0A,
1118 0x00,
1119 0x00,
1120 0x00,
1121 0x00, // uint32_t, 0
1122 0x09,
1123 0x40,
1124 0x00, // uint16_t (handle) = 0x4000
1125 0x09,
1126 0xfe,
1127 0xed, // uint16_t (0xfeed)
1128 0x09,
1129 0x40,
1130 0x01, // uint16_t (handle) = 0x4001
1131 0x19,
1132 0x00,
1133 0x01, // UUID (kSDP)
1134 0x09,
1135 0x40,
1136 0x02, // uint32_t (handle) = 0x4002
1137 0x0A,
1138 0xc0,
1139 0xde,
1140 0xca,
1141 0xde, // uint32_t = 0xc0decade
1142 0x09,
1143 0x40,
1144 0x03, // uint32_t (handle) = 0x4003
1145 0x25,
1146 0x04,
1147 0xf0, // Partial String: '' (type, length, first char)
1148 0x04,
1149 0x00,
1150 0x00,
1151 0x00,
1152 0x24 // Continuation state (4 bytes: 36 bytes offset)
1153 );
1154
1155 auto pdu = resp.GetPDU(
1156 0xFFFF /* no max */, kTransactionID, kMinMaxSize, BufferView());
1157 EXPECT_TRUE(ContainersEqual(kExpectedContinuation, *pdu));
1158
1159 const StaticByteBuffer kExpectedRemaining(
1160 0x05, // ServiceSearchAttributeResponse
1161 UpperBits(kTransactionID),
1162 LowerBits(kTransactionID), // Transaction ID
1163 0x00,
1164 0x0e, // Param Length (14 bytes)
1165 0x00,
1166 0x0b, // AttributeListsByteCount (12 bytes)
1167 // AttributeLists (continued)
1168 0x9f,
1169 0x92,
1170 0x96, // Remaining 3 bytes of String: ''
1171 0x09,
1172 0x40,
1173 0x05, // uint16_t (handle) = 0x4005
1174 0x0A,
1175 0xc0,
1176 0xde,
1177 0xb4,
1178 0xbe, // value: uint32_t (0xC0DEB4BE)
1179 0x00 // Continuation state (none)
1180 );
1181
1182 pdu = resp.GetPDU(0xFFFF /* no max */,
1183 kTransactionID,
1184 kMinMaxSize,
1185 StaticByteBuffer(0x00, 0x00, 0x00, 0x24));
1186 EXPECT_TRUE(ContainersEqual(kExpectedRemaining, *pdu));
1187 }
1188
TEST(PDUTest,ServiceSearchAttributeRequestParse)1189 TEST(PDUTest, ServiceSearchAttributeRequestParse) {
1190 const StaticByteBuffer kSDPL2CAPAllAttributes(
1191 // Service search pattern
1192 0x35,
1193 0x03, // Sequence uint8 3 bytes
1194 0x19,
1195 0x01,
1196 0x00, // UUID: Protocol: L2CAP
1197 0xF0,
1198 0x0F, // Maximum attribute byte count: (max = 61455)
1199 // Attribute ID List
1200 0x35,
1201 0x05, // Sequence uint8 5 bytes
1202 0x0A, // uint32_t
1203 0x00,
1204 0x00,
1205 0xFF,
1206 0xFF, // Attribute range: 0x000 - 0xFFFF (All of them)
1207 0x00 // No continuation state
1208 );
1209
1210 ServiceSearchAttributeRequest req(kSDPL2CAPAllAttributes);
1211
1212 EXPECT_TRUE(req.valid());
1213 EXPECT_EQ(1u, req.service_search_pattern().size());
1214 EXPECT_EQ(1u, req.service_search_pattern().count(protocol::kL2CAP));
1215 EXPECT_EQ(1u, req.attribute_ranges().size());
1216 EXPECT_EQ(0x0000, req.attribute_ranges().front().start);
1217 EXPECT_EQ(0xFFFF, req.attribute_ranges().front().end);
1218 EXPECT_EQ(61455, req.max_attribute_byte_count());
1219
1220 const auto kContinued =
1221 StaticByteBuffer(0x35,
1222 0x03, // Sequence uint8 3 bytes
1223 0x19,
1224 0x01,
1225 0x00, // UUID: Protocol: L2CAP
1226 0x00,
1227 0x0F, // Maximum attribute byte count: (max = 15)
1228 // Attribute ID List
1229 0x35,
1230 0x06, // Sequence uint8 6 bytes
1231 0x09, // uint16_t
1232 0x00,
1233 0x01, // Attribute ID: 1
1234 0x09, // uint16_t
1235 0x00,
1236 0x02, // Attribute ID: 2
1237 0x03,
1238 0x12,
1239 0x34,
1240 0x56 // Continuation state
1241 );
1242
1243 ServiceSearchAttributeRequest req_cont_state(kContinued);
1244
1245 EXPECT_TRUE(req_cont_state.valid());
1246 EXPECT_EQ(1u, req.service_search_pattern().size());
1247 EXPECT_EQ(1u, req.service_search_pattern().count(protocol::kL2CAP));
1248 EXPECT_EQ(2u, req_cont_state.attribute_ranges().size());
1249 EXPECT_EQ(0x0001, req_cont_state.attribute_ranges().front().start);
1250 EXPECT_EQ(0x0001, req_cont_state.attribute_ranges().front().end);
1251 EXPECT_EQ(0x0002, req_cont_state.attribute_ranges().back().start);
1252 EXPECT_EQ(0x0002, req_cont_state.attribute_ranges().back().end);
1253 EXPECT_EQ(15, req_cont_state.max_attribute_byte_count());
1254
1255 // Too short request.
1256 ServiceSearchAttributeRequest req_short((BufferView()));
1257
1258 EXPECT_FALSE(req_short.valid());
1259
1260 const auto kInvalidMaxBytes =
1261 StaticByteBuffer(0x35,
1262 0x03, // Sequence uint8 3 bytes
1263 0x19,
1264 0x01,
1265 0x00, // UUID: Protocol: L2CAP
1266 0x00,
1267 0x04, // Maximum attribute byte count (4)
1268 // Attribute ID List
1269 0x35,
1270 0x03, // Sequence uint8 3 bytes
1271 0x09,
1272 0x00,
1273 0x02, // uint16_t (2)
1274 0x00 // No continuation state
1275 );
1276
1277 ServiceSearchAttributeRequest req_minmax(kInvalidMaxBytes);
1278
1279 EXPECT_FALSE(req_minmax.valid());
1280
1281 // Invalid order of the attributes.
1282 const auto kInvalidAttributeListOrder =
1283 StaticByteBuffer(0x35,
1284 0x03, // Sequence uint8 3 bytes
1285 0x19,
1286 0x01,
1287 0x00, // UUID: Protocol: L2CAP
1288 0xFF,
1289 0xFF, // Maximum attribute byte count: (max = 65535)
1290 // Attribute ID List
1291 0x35,
1292 0x06, // Sequence uint8 6 bytes
1293 0x09,
1294 0x00,
1295 0x02, // uint16_t (2)
1296 0x09,
1297 0x00,
1298 0x01, // uint16_t (1)
1299 0x00 // No continuation state
1300 );
1301
1302 ServiceSearchAttributeRequest req_order(kInvalidAttributeListOrder);
1303
1304 EXPECT_FALSE(req_short.valid());
1305
1306 // AttributeID List has invalid items
1307 const auto kInvalidAttributeList =
1308 StaticByteBuffer(0x35,
1309 0x03, // Sequence uint8 3 bytes
1310 0x19,
1311 0x01,
1312 0x00, // UUID: Protocol: L2CAP
1313 0xFF,
1314 0xFF, // Maximum attribute byte count: (max = 65535)
1315 // Attribute ID List
1316 0x35,
1317 0x06, // Sequence uint8 6 bytes
1318 0x09,
1319 0x00,
1320 0x02, // uint16_t (2)
1321 0x19,
1322 0x00,
1323 0x01, // UUID (0x0001)
1324 0x00 // No continuation state
1325 );
1326
1327 ServiceSearchAttributeRequest req_baditems(kInvalidAttributeList);
1328
1329 EXPECT_FALSE(req_baditems.valid());
1330
1331 const auto kInvalidNoItems =
1332 StaticByteBuffer(0x35,
1333 0x00, // Sequence uint8 0 bytes
1334 0xF0,
1335 0x0F, // Maximum attribute byte count (61455)
1336 // Attribute ID List
1337 0x35,
1338 0x03, // Sequence uint8 3 bytes
1339 0x09,
1340 0x00,
1341 0x02, // uint16_t (2)
1342 0x00 // No continuation state
1343 );
1344
1345 ServiceSearchAttributeRequest req_noitems(kInvalidNoItems);
1346 EXPECT_FALSE(req_noitems.valid());
1347
1348 const auto kInvalidNoAttributes =
1349 StaticByteBuffer(0x35,
1350 0x03, // Sequence uint8 3 bytes
1351 0x19,
1352 0x01,
1353 0x00, // UUID: Protocol: L2CAP
1354 0xF0,
1355 0x0F, // Maximum attribute byte count (61455)
1356 // Attribute ID List
1357 0x35,
1358 0x00, // Sequence uint8 0 bytes
1359 0x00 // No continuation state
1360 );
1361
1362 ServiceSearchAttributeRequest req_noattributes(kInvalidNoAttributes);
1363 EXPECT_FALSE(req_noattributes.valid());
1364
1365 const StaticByteBuffer kInvalidTooManyItems(
1366 // ServiceSearchPattern
1367 0x35,
1368 0x27, // Sequence uint8 27 bytes
1369 0x19,
1370 0x30,
1371 0x01, // 13 UUIDs in the search
1372 0x19,
1373 0x30,
1374 0x02,
1375 0x19,
1376 0x30,
1377 0x03,
1378 0x19,
1379 0x30,
1380 0x04,
1381 0x19,
1382 0x30,
1383 0x05,
1384 0x19,
1385 0x30,
1386 0x06,
1387 0x19,
1388 0x30,
1389 0x07,
1390 0x19,
1391 0x30,
1392 0x08,
1393 0x19,
1394 0x30,
1395 0x09,
1396 0x19,
1397 0x30,
1398 0x10,
1399 0x19,
1400 0x30,
1401 0x11,
1402 0x19,
1403 0x30,
1404 0x12,
1405 0x19,
1406 0x30,
1407 0x13,
1408 0xF0,
1409 0x0F, // Maximum attribute byte count (61455)
1410 0x35,
1411 0x03, // Sequence uint8 3 bytes
1412 0x09,
1413 0x00,
1414 0x02, // uint16_t (2)
1415 0x00 // No continuation state
1416 );
1417
1418 ServiceSearchAttributeRequest req_toomany(kInvalidTooManyItems);
1419 EXPECT_FALSE(req_toomany.valid());
1420 }
1421
TEST(PDUTest,ServiceSearchAttributeRequestGetPDU)1422 TEST(PDUTest, ServiceSearchAttributeRequestGetPDU) {
1423 ServiceSearchAttributeRequest req;
1424 req.AddAttribute(0xF00F);
1425 req.AddAttributeRange(0x0001, 0xBECA);
1426
1427 req.set_search_pattern({protocol::kATT, protocol::kL2CAP});
1428 req.set_max_attribute_byte_count(32);
1429
1430 const auto kExpected = StaticByteBuffer(kServiceSearchAttributeRequest,
1431 0x12,
1432 0x34, // transaction id
1433 0x00,
1434 0x15, // Parameter Length (21 bytes)
1435 // ServiceSearchPattern
1436 0x35,
1437 0x06, // Sequence uint8 6 bytes
1438 0x19,
1439 0x00,
1440 0x07, // UUID (ATT)
1441 0x19,
1442 0x01,
1443 0x00, // UUID (L2CAP)
1444 0x00,
1445 0x20, // MaxAttributeByteCount (32)
1446 // Attribute ID list
1447 0x35,
1448 0x08, // Sequence uint8 8 bytes
1449 0x0A,
1450 0x00,
1451 0x01,
1452 0xBE,
1453 0xCA, // uint32_t (0x0001BECA)
1454 0x09,
1455 0xF0,
1456 0x0F, // uint16_t (0xF00F)
1457 0x00 // No continuation state
1458 );
1459
1460 const auto kExpected2 = StaticByteBuffer(kServiceSearchAttributeRequest,
1461 0x12,
1462 0x34, // transaction id
1463 0x00,
1464 0x15, // Parameter Length (21 bytes)
1465 // ServiceSearchPattern
1466 0x35,
1467 0x06, // Sequence uint8 6 bytes
1468 0x19,
1469 0x01,
1470 0x00, // UUID (L2CAP)
1471 0x19,
1472 0x00,
1473 0x07, // UUID (ATT)
1474 0x00,
1475 0x20, // MaxAttributeByteCount (32)
1476 // Attribute ID list
1477 0x35,
1478 0x08, // Sequence uint8 8 bytes
1479 0x0A,
1480 0x00,
1481 0x01,
1482 0xBE,
1483 0xCA, // uint32_t (0x0001BECA)
1484 0x09,
1485 0xF0,
1486 0x0F, // uint16_t (0xF00F)
1487 0x00 // No continuation state
1488 );
1489
1490 auto pdu = req.GetPDU(0x1234);
1491 EXPECT_TRUE(MatchesOneOf(kExpected, kExpected2, *pdu));
1492 }
1493
TEST(PDUTest,ServiceSearchAttributeRequestGetPDUTooManyAttributes)1494 TEST(PDUTest, ServiceSearchAttributeRequestGetPDUTooManyAttributes) {
1495 ServiceSearchAttributeRequest req;
1496 // Skip attributes to prevent them from being combined into a range.
1497 for (AttributeId attr = 0x0000; attr <= kMaxAttributeRangesInRequest * 2;
1498 attr += 2) {
1499 req.AddAttribute(attr);
1500 }
1501
1502 req.set_search_pattern({protocol::kATT, protocol::kL2CAP});
1503 req.set_max_attribute_byte_count(32);
1504
1505 EXPECT_EQ(req.GetPDU(0x1234), nullptr);
1506 }
1507
TEST(PDUTest,ServiceSearchAttributeResponseParse)1508 TEST(PDUTest, ServiceSearchAttributeResponseParse) {
1509 const StaticByteBuffer kValidResponseEmpty(0x00,
1510 0x02, // AttributeListsByteCount
1511 // (2 bytes) Attribute List
1512 0x35,
1513 0x00, // Sequence uint8 0 bytes
1514 0x00 // No continuation state
1515 );
1516
1517 ServiceSearchAttributeResponse resp;
1518 auto status = resp.Parse(kValidResponseEmpty);
1519
1520 EXPECT_EQ(fit::ok(), status);
1521 EXPECT_TRUE(resp.complete());
1522 EXPECT_EQ(0u, resp.num_attribute_lists());
1523
1524 const StaticByteBuffer kValidResponseItems(
1525 0x00,
1526 0x14, // AttributeListsByteCount (20 bytes)
1527 // Wrapping Attribute List
1528 0x35,
1529 0x12, // Sequence uint8 18 bytes
1530 // Attribute List
1531 0x35,
1532 0x10, // Sequence uint8 16 bytes
1533 0x09,
1534 0x00,
1535 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
1536 0x0A,
1537 0xFE,
1538 0xED,
1539 0xBE,
1540 0xEF, // Element: uint32_t (0xFEEDBEEF)
1541 0x09,
1542 0x00,
1543 0x01, // Handle: uint16_t (1 = kServiceClassIdList)
1544 0x35,
1545 0x03,
1546 0x19,
1547 0x11,
1548 0x01, // Element: Sequence (3) { UUID(0x1101) }
1549 0x00 // No continuation state
1550 );
1551
1552 status = resp.Parse(kValidResponseItems);
1553
1554 EXPECT_EQ(fit::ok(), status);
1555 EXPECT_TRUE(resp.complete());
1556 EXPECT_EQ(1u, resp.num_attribute_lists());
1557 EXPECT_EQ(2u, resp.attributes(0).size());
1558 auto it = resp.attributes(0).find(0x0000);
1559 EXPECT_NE(resp.attributes(0).end(), it);
1560 EXPECT_EQ(DataElement::Type::kUnsignedInt, it->second.type());
1561
1562 it = resp.attributes(0).find(0x0001);
1563 EXPECT_NE(resp.attributes(0).end(), it);
1564 EXPECT_EQ(DataElement::Type::kSequence, it->second.type());
1565
1566 const StaticByteBuffer kValidResponseTwoLists(
1567 0x00,
1568 0x1E, // AttributeListsByteCount (30 bytes)
1569 // Wrapping Attribute List
1570 0x35,
1571 0x1C, // Sequence uint8 28 bytes
1572 // Attribute List 0 (first service)
1573 0x35,
1574 0x08, // Sequence uint8 8 bytes
1575 0x09,
1576 0x00,
1577 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
1578 0x0A,
1579 0xFE,
1580 0xED,
1581 0xBE,
1582 0xEF, // Element: uint32_t (0xFEEDBEEF)
1583 // Attribute List 1 (second service)
1584 0x35,
1585 0x10, // Sequence uint8 16 bytes
1586 0x09,
1587 0x00,
1588 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
1589 0x0A,
1590 0xFE,
1591 0xDB,
1592 0xAC,
1593 0x01, // Element: uint32_t (0xFEDBAC01)
1594 0x09,
1595 0x00,
1596 0x01, // Handle: uint16_t (1 = kServiceClassIdList)
1597 0x35,
1598 0x03,
1599 0x19,
1600 0x11,
1601 0x01, // Element: Sequence (3) { UUID(0x1101) }
1602 0x00 // No continuation state
1603 );
1604
1605 ServiceSearchAttributeResponse resp2;
1606 status = resp2.Parse(kValidResponseTwoLists);
1607
1608 EXPECT_EQ(fit::ok(), status);
1609 EXPECT_TRUE(resp2.complete());
1610 EXPECT_EQ(2u, resp2.num_attribute_lists());
1611
1612 EXPECT_EQ(1u, resp2.attributes(0).size());
1613 it = resp2.attributes(0).find(0x0000);
1614 EXPECT_NE(resp2.attributes(0).end(), it);
1615 EXPECT_EQ(DataElement::Type::kUnsignedInt, it->second.type());
1616
1617 EXPECT_EQ(2u, resp2.attributes(1).size());
1618 it = resp2.attributes(1).find(0x0000);
1619 EXPECT_NE(resp2.attributes(1).end(), it);
1620 EXPECT_EQ(DataElement::Type::kUnsignedInt, it->second.type());
1621
1622 // Note: see test below, some peers will send in the wrong order.
1623 // We still will fail if the peer sends us two of the same type.
1624 const StaticByteBuffer kInvalidItemsDuplicateAttribute(
1625 0x00,
1626 0x14, // AttributeListByteCount (20 bytes)
1627 // Wrapping Attribute List
1628 0x35,
1629 0x12, // Sequence uint8 18 bytes
1630 // Attribute List
1631 0x35,
1632 0x10, // Sequence uint8 16 bytes
1633 0x09,
1634 0x00,
1635 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
1636 0x0A,
1637 0xB0,
1638 0xBA,
1639 0xCA,
1640 0xFE, // Element: uint32_t (0xB0BACAFE)
1641 0x09,
1642 0x00,
1643 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
1644 0x0A,
1645 0xFE,
1646 0xED,
1647 0xBE,
1648 0xEF, // Element: uint32_t (0xFEEDBEEF)
1649 0x00 // No continuation state
1650 );
1651
1652 ServiceSearchAttributeResponse resp3;
1653 status = resp3.Parse(kInvalidItemsDuplicateAttribute);
1654
1655 EXPECT_TRUE(status.is_error());
1656 EXPECT_EQ(0u, resp3.num_attribute_lists());
1657
1658 const StaticByteBuffer kInvalidHandleWrongType(
1659 0x00,
1660 0x13, // AttributeListByteCount (19 bytes)
1661 // Wrapping Attribute List
1662 0x35,
1663 0x11, // Sequence uint8 17 bytes
1664 // Attribute List
1665 0x35,
1666 0x0F, // Sequence uint8 15 bytes
1667 0x09,
1668 0x00,
1669 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
1670 0x0A,
1671 0xFE,
1672 0xED,
1673 0xBE,
1674 0xEF, // Element: uint32_t (0xFEEDBEEF)
1675 0x08,
1676 0x01, // Handle: uint8_t (!) (1 = kServiceClassIdList)
1677 0x35,
1678 0x03,
1679 0x19,
1680 0x11,
1681 0x01, // Element: Sequence (3) { UUID(0x1101) }
1682 0x00 // No continuation state
1683 );
1684
1685 ServiceAttributeResponse resp_wrongtype;
1686 status = resp_wrongtype.Parse(kInvalidHandleWrongType);
1687
1688 EXPECT_TRUE(status.is_error());
1689
1690 const StaticByteBuffer kInvalidByteCount(
1691 0x00,
1692 0x12, // AttributeListsByteCount (18 bytes)
1693 0x35,
1694 0x11, // Sequence uint8 17 bytes
1695 // Attribute List
1696 0x35,
1697 0x0F, // Sequence uint8 15 bytes
1698 0x09,
1699 0x00,
1700 0x01, // Handle: uint16_t (1)
1701 0x35,
1702 0x03,
1703 0x19,
1704 0x11,
1705 0x01, // Element: Sequence (3) { UUID(0x1101) }
1706 0x09,
1707 0x00,
1708 0x00, // Handle: uint16_t (0)
1709 0x25,
1710 0x02,
1711 'h',
1712 'i', // Element: String ('hi')
1713 0x00 // No continuation state
1714 );
1715
1716 status = resp3.Parse(kInvalidByteCount);
1717
1718 EXPECT_TRUE(status.is_error());
1719
1720 // Sending too much data eventually fails.
1721 auto kContinuationPacket = DynamicByteBuffer(4096);
1722 // Put the correct byte count at the front: 4096 - 2 (byte count) - 5
1723 // (continuation size)
1724 const StaticByteBuffer kAttributeListByteCount(0x0F, 0xF9);
1725 kContinuationPacket.Write(kAttributeListByteCount, 0);
1726 // Put the correct continuation at the end.
1727 const StaticByteBuffer kContinuation(0x04, 0xF0, 0x9F, 0x92, 0x96);
1728 kContinuationPacket.Write(kContinuation, kContinuationPacket.size() - 5);
1729
1730 ServiceSearchAttributeResponse resp4;
1731 status = resp4.Parse(kContinuationPacket);
1732 EXPECT_EQ(ToResult(HostError::kInProgress), status);
1733 while (status == ToResult(HostError::kInProgress)) {
1734 status = resp4.Parse(kContinuationPacket);
1735 }
1736 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
1737 }
1738
1739 // Some peers will send the attributes in the wrong order.
1740 // As long as they are not duplicate attributes, we are flexible to this.
TEST(PDUTest,ServiceSearchAttributeResponseParseContinuationWrongOrder)1741 TEST(PDUTest, ServiceSearchAttributeResponseParseContinuationWrongOrder) {
1742 // Attributes can come in the wrong order.
1743 const StaticByteBuffer kItemsWrongOrder(
1744 0x00,
1745 0x14, // AttributeListByteCount (20 bytes)
1746 // Wrapping Attribute List
1747 0x35,
1748 0x12, // Sequence uint8 18 bytes
1749 // Attribute List
1750 0x35,
1751 0x10, // Sequence uint8 16 bytes
1752 0x09,
1753 0x00,
1754 0x01, // Handle: uint16_t (1 = kServiceClassIdList)
1755 0x35,
1756 0x03,
1757 0x19,
1758 0x11,
1759 0x01, // Element: Sequence (3) { UUID(0x1101) }
1760 0x09,
1761 0x00,
1762 0x00, // Handle: uint16_t (0 = kServiceRecordHandle)
1763 0x0A,
1764 0xFE,
1765 0xED,
1766 0xBE,
1767 0xEF, // Element: uint32_t (0xFEEDBEEF)
1768 0x00 // No continuation state
1769 );
1770
1771 ServiceSearchAttributeResponse resp_simple;
1772 auto status = resp_simple.Parse(kItemsWrongOrder);
1773
1774 EXPECT_EQ(fit::ok(), status);
1775
1776 // Packets seen in real-world testing, a more complicated example.
1777 const StaticByteBuffer kFirstPacket(
1778 0x00,
1779 0x77, // AttributeListsByteCount (119 bytes (in this packet))
1780 0x35,
1781 0x7e, // Wrapping attribute list sequence: 126 bytes
1782 0x35,
1783 0x33, // Begin attribute list 1 (51 bytes)
1784 0x09,
1785 0x00,
1786 0x01, // Attribute 0x01
1787 0x35,
1788 0x06,
1789 0x19,
1790 0x11,
1791 0x0e,
1792 0x19,
1793 0x11,
1794 0x0f, // Attribute 0x01 data: 2 UUIDs list
1795 0x09,
1796 0x00,
1797 0x04, // Attribute 0x04
1798 0x35,
1799 0x10,
1800 0x35,
1801 0x06,
1802 0x19,
1803 0x01,
1804 0x00,
1805 0x09,
1806 0x00,
1807 0x17,
1808 0x35,
1809 0x06,
1810 0x19,
1811 0x00,
1812 0x17,
1813 0x09,
1814 0x01,
1815 0x04, // Attribute 0x04 data
1816 0x09,
1817 0x00,
1818 0x09, // Attribute 0x09
1819 0x35,
1820 0x08,
1821 0x35,
1822 0x06,
1823 0x19,
1824 0x11,
1825 0x0e,
1826 0x09,
1827 0x01,
1828 0x05, // Attribute 0x09 data
1829 0x09,
1830 0x03,
1831 0x11, // Attribute 0x311
1832 0x09,
1833 0x00,
1834 0x01, // Attribute 0x311 data: uint16 (0x01)
1835 0x35,
1836 0x47, // Begin attribute list 2 (71 bytes)
1837 0x09,
1838 0x00,
1839 0x01, // Attribute 0x01
1840 0x35,
1841 0x03,
1842 0x19,
1843 0x11,
1844 0x0c, // Attribute 0x01 data, Sequence of 1 UUID
1845 0x09,
1846 0x00,
1847 0x04, // Attribute 0x04
1848 0x35,
1849 0x10,
1850 0x35,
1851 0x06,
1852 0x19,
1853 0x01,
1854 0x00,
1855 0x09,
1856 0x00,
1857 0x17,
1858 0x35,
1859 0x06,
1860 0x19,
1861 0x00,
1862 0x17,
1863 0x09,
1864 0x01,
1865 0x04, // Attribute 0x04 data
1866 0x09,
1867 0x00,
1868 0x0d, // Attribute 0x0d
1869 0x35,
1870 0x12,
1871 0x35,
1872 0x10,
1873 0x35,
1874 0x06,
1875 0x19,
1876 0x01,
1877 0x00,
1878 0x09,
1879 0x00,
1880 0x1b,
1881 0x35,
1882 0x06,
1883 0x19,
1884 0x00,
1885 0x17,
1886 0x09,
1887 0x01,
1888 0x04, // Attribute 0x0d data
1889 0x09,
1890 0x00,
1891 0x09, // Attribute 0x09
1892 0x35,
1893 0x08,
1894 0x35,
1895 0x06,
1896 0x19,
1897 0x11,
1898 0x0e,
1899 0x01, // Start of Attribute 0x09 data
1900 // (continued in next packet)
1901 0x01 // Continuation state (yes, one byte, 0x01)
1902 );
1903
1904 ServiceSearchAttributeResponse resp;
1905 status = resp.Parse(kFirstPacket);
1906 EXPECT_EQ(ToResult(HostError::kInProgress), status);
1907
1908 const StaticByteBuffer kSecondPacket(
1909 0x00,
1910 0x09, // AttributeListsByteCount (9 bytes)
1911 // 9 bytes continuing the previous response
1912 0x09,
1913 0x01,
1914 0x05, // Continuation of previous 0x09 attribute
1915 0x09,
1916 0x03,
1917 0x11, // Attribute 0x311
1918 0x09,
1919 0x00,
1920 0x02, // Attribute 0x0311 data: uint16(0x02)
1921 0x00 // No continuation state.
1922 );
1923
1924 status = resp.Parse(kSecondPacket);
1925 EXPECT_EQ(fit::ok(), status);
1926 }
1927
TEST(PDUTest,ServiceSearchAttributeResponseGetPDU)1928 TEST(PDUTest, ServiceSearchAttributeResponseGetPDU) {
1929 ServiceSearchAttributeResponse resp;
1930
1931 // Even if set in the wrong order, attributes should be sorted in the PDU.
1932 resp.SetAttribute(0, 0x4000, DataElement(uint16_t{0xfeed}));
1933 resp.SetAttribute(0, 0x4001, DataElement(protocol::kSDP));
1934 resp.SetAttribute(0, kServiceRecordHandle, DataElement(uint32_t{0}));
1935
1936 // Attributes do not need to be continuous
1937 resp.SetAttribute(5, kServiceRecordHandle, DataElement(uint32_t{0x10002000}));
1938
1939 const uint16_t kTransactionID = 0xfeed;
1940
1941 const StaticByteBuffer kExpected(
1942 0x07, // ServiceSearchAttributeResponse
1943 UpperBits(kTransactionID),
1944 LowerBits(kTransactionID), // Transaction ID
1945 0x00,
1946 0x25, // Param Length (37 bytes)
1947 0x00,
1948 0x22, // AttributeListsByteCount (34 bytes)
1949 // AttributeLists
1950 0x35,
1951 0x20, // Sequence uint8 32 bytes
1952 0x35,
1953 0x14, // Sequence uint8 20 bytes
1954 0x09,
1955 0x00,
1956 0x00, // uint16_t (handle) = kServiceRecordHandle
1957 0x0A,
1958 0x00,
1959 0x00,
1960 0x00,
1961 0x00, // uint32_t, 0
1962 0x09,
1963 0x40,
1964 0x00, // uint16_t (handle) = 0x4000
1965 0x09,
1966 0xfe,
1967 0xed, // uint16_t (0xfeed)
1968 0x09,
1969 0x40,
1970 0x01, // uint16_t (handle) = 0x4001
1971 0x19,
1972 0x00,
1973 0x01, // UUID (kSDP)
1974 0x35,
1975 0x08, // Sequence uint8 8 bytes
1976 0x09,
1977 0x00,
1978 0x00, // uint16_t (handle) = kServiceRecordHandle
1979 0x0A,
1980 0x10,
1981 0x00,
1982 0x20,
1983 0x00, // value: uint32_t (0x10002000)
1984 0x00 // Continuation state (none)
1985 );
1986
1987 auto pdu = resp.GetPDU(
1988 0xFFFF /* no max */, kTransactionID, kDefaultMaxSize, BufferView());
1989
1990 EXPECT_TRUE(ContainersEqual(kExpected, *pdu));
1991 }
1992
TEST(PDUTest,ServiceSearchAttributeResponseGetPDU_MaxSize)1993 TEST(PDUTest, ServiceSearchAttributeResponseGetPDU_MaxSize) {
1994 ServiceSearchAttributeResponse resp;
1995
1996 // Even if set in the wrong order, attributes should be sorted in the PDU.
1997 resp.SetAttribute(0, 0x4000, DataElement(uint16_t{0xfeed}));
1998 resp.SetAttribute(0, 0x4001, DataElement(protocol::kSDP));
1999 resp.SetAttribute(0, 0x4002, DataElement(uint32_t{0xc0decade}));
2000 DataElement str;
2001 str.Set(std::string(""));
2002 resp.SetAttribute(0, 0x4003, std::move(str));
2003 resp.SetAttribute(0, kServiceRecordHandle, DataElement(uint32_t{0}));
2004
2005 // Attributes do not need to be continuous
2006 resp.SetAttribute(5, kServiceRecordHandle, DataElement(uint32_t{0x10002000}));
2007
2008 const uint16_t kTransactionID = 0xfeed;
2009
2010 const StaticByteBuffer kExpectedContinuation(
2011 0x07, // ServiceSearchAttributeResponse
2012 UpperBits(kTransactionID),
2013 LowerBits(kTransactionID), // Transaction ID
2014 0x00,
2015 0x2B, // Param Length (43 bytes)
2016 0x00,
2017 0x24, // AttributeListsByteCount (36 bytes)
2018 // AttributeLists
2019 0x35,
2020 0x31, // Sequence uint8 49 bytes = 37 + 2 + 8 + 2
2021 0x35,
2022 0x25, // Sequence uint8 37 bytes
2023 0x09,
2024 0x00,
2025 0x00, // uint16_t (handle) = kServiceRecordHandle
2026 0x0A,
2027 0x00,
2028 0x00,
2029 0x00,
2030 0x00, // uint32_t, 0
2031 0x09,
2032 0x40,
2033 0x00, // uint16_t (handle) = 0x4000
2034 0x09,
2035 0xfe,
2036 0xed, // uint16_t (0xfeed)
2037 0x09,
2038 0x40,
2039 0x01, // uint16_t (handle) = 0x4001
2040 0x19,
2041 0x00,
2042 0x01, // UUID (kSDP)
2043 0x09,
2044 0x40,
2045 0x02, // uint32_t (handle) = 0x4002
2046 0x0A,
2047 0xc0,
2048 0xde,
2049 0xca,
2050 0xde, // uint32_t = 0xc0decade
2051 0x09,
2052 0x40,
2053 0x03, // uint32_t (handle) = 0x4003
2054 0x25, // Partial String: '' (just the type)
2055 0x04,
2056 0x00,
2057 0x00,
2058 0x00,
2059 0x24 // Continuation state (4 bytes: 36 bytes offset)
2060 );
2061
2062 auto pdu = resp.GetPDU(
2063 0xFFFF /* no max */, kTransactionID, kMinMaxSize, BufferView());
2064 EXPECT_TRUE(ContainersEqual(kExpectedContinuation, *pdu));
2065
2066 const StaticByteBuffer kExpectedRemaining(
2067 0x07, // ServiceSearchAttributeResponse
2068 UpperBits(kTransactionID),
2069 LowerBits(kTransactionID), // Transaction ID
2070 0x00,
2071 0x12, // Param Length (18 bytes)
2072 0x00,
2073 0x0F, // AttributeListsByteCount (14 bytes)
2074 // AttributeLists (continued)
2075 0x04,
2076 0xf0,
2077 0x9f,
2078 0x92,
2079 0x96, // Remaining 5 bytes of String: ''
2080 0x35,
2081 0x08, // Sequence uint8 8 bytes
2082 0x09,
2083 0x00,
2084 0x00, // uint16_t (handle) = kServiceRecordHandle
2085 0x0A,
2086 0x10,
2087 0x00,
2088 0x20,
2089 0x00, // value: uint32_t (0x10002000)
2090 0x00 // Continuation state (none)
2091 );
2092
2093 pdu = resp.GetPDU(0xFFFF /* no max */,
2094 kTransactionID,
2095 kMinMaxSize,
2096 StaticByteBuffer(0x00, 0x00, 0x00, 0x24));
2097 EXPECT_TRUE(ContainersEqual(kExpectedRemaining, *pdu));
2098 }
2099
TEST(PDUTest,ResponseOutOfRangeContinuation)2100 TEST(PDUTest, ResponseOutOfRangeContinuation) {
2101 ServiceSearchResponse rsp_search;
2102 rsp_search.set_service_record_handle_list({1, 2, 3, 4});
2103 auto buf = rsp_search.GetPDU(0xFFFF, 0x0110, kDefaultMaxSize, BufferView());
2104 EXPECT_TRUE(buf);
2105 // Out of Range (continuation is zero-indexed)
2106 uint16_t handle_count =
2107 htobe16(rsp_search.service_record_handle_list().size());
2108 auto service_search_cont = DynamicByteBuffer(sizeof(uint16_t));
2109 service_search_cont.WriteObj(handle_count, 0);
2110 buf = rsp_search.GetPDU(0xFFFF, 0x0110, kDefaultMaxSize, service_search_cont);
2111 EXPECT_FALSE(buf);
2112 // Wrong size continuation state
2113 buf = rsp_search.GetPDU(
2114 0xFFFF, 0x0110, kDefaultMaxSize, StaticByteBuffer(0x01, 0xFF, 0xFF));
2115 EXPECT_FALSE(buf);
2116
2117 ServiceAttributeResponse rsp_attr;
2118 rsp_attr.set_attribute(1, DataElement(uint32_t{45}));
2119
2120 buf = rsp_attr.GetPDU(0xFFFF, 0x0110, kDefaultMaxSize, BufferView());
2121 EXPECT_TRUE(buf);
2122
2123 uint32_t rsp_size = htobe32(buf->size() + 5);
2124 auto too_large_cont = DynamicByteBuffer(sizeof(uint32_t));
2125 too_large_cont.WriteObj(rsp_size, 0);
2126 buf = rsp_attr.GetPDU(0xFFFF, 0x0110, kDefaultMaxSize, too_large_cont);
2127
2128 EXPECT_FALSE(buf);
2129
2130 ServiceSearchAttributeResponse rsp_search_attr;
2131
2132 rsp_search_attr.SetAttribute(0, 0x4000, DataElement(uint16_t{0xfeed}));
2133 rsp_search_attr.SetAttribute(0, 0x4001, DataElement(protocol::kSDP));
2134 rsp_search_attr.SetAttribute(
2135 0, kServiceRecordHandle, DataElement(uint32_t{0}));
2136 rsp_search_attr.SetAttribute(
2137 5, kServiceRecordHandle, DataElement(uint32_t{0x10002000}));
2138
2139 buf = rsp_search_attr.GetPDU(0xFFFF, 0x0110, kDefaultMaxSize, BufferView());
2140
2141 EXPECT_TRUE(buf);
2142
2143 rsp_size = htobe32(buf->size() + 5);
2144 too_large_cont.WriteObj(rsp_size, 0);
2145 buf = rsp_attr.GetPDU(0xFFFF, 0x0110, kDefaultMaxSize, too_large_cont);
2146
2147 EXPECT_FALSE(buf);
2148 }
2149
2150 } // namespace
2151 } // namespace bt::sdp
2152