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