• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_proxy/proxy_host.h"
16 
17 #include <cstdint>
18 
19 #include "pw_bluetooth/emboss_util.h"
20 #include "pw_bluetooth/hci_commands.emb.h"
21 #include "pw_bluetooth/hci_common.emb.h"
22 #include "pw_bluetooth/hci_data.emb.h"
23 #include "pw_bluetooth/hci_events.emb.h"
24 #include "pw_bluetooth/hci_h4.emb.h"
25 #include "pw_bluetooth/l2cap_frames.emb.h"
26 #include "pw_bluetooth_proxy/h4_packet.h"
27 #include "pw_bluetooth_proxy/internal/logical_transport.h"
28 #include "pw_bluetooth_proxy/l2cap_channel_common.h"
29 #include "pw_bluetooth_proxy/l2cap_status_delegate.h"
30 #include "pw_bluetooth_proxy_private/test_utils.h"
31 #include "pw_containers/flat_map.h"
32 #include "pw_function/function.h"
33 #include "pw_log/log.h"
34 #include "pw_span/span.h"
35 #include "pw_status/status.h"
36 #include "pw_unit_test/framework.h"
37 #include "pw_unit_test/status_macros.h"
38 
39 namespace pw::bluetooth::proxy {
40 
41 namespace {
42 
43 using containers::FlatMap;
44 
45 // Return a populated H4 command buffer of a type that proxy host doesn't
46 // interact with.
PopulateNoninteractingToControllerBuffer(H4PacketWithH4 & h4_packet)47 Status PopulateNoninteractingToControllerBuffer(H4PacketWithH4& h4_packet) {
48   return CreateAndPopulateToControllerView<emboss::InquiryCommandWriter>(
49              h4_packet,
50              emboss::OpCode::LINK_KEY_REQUEST_REPLY,
51              /*parameter_total_size=*/0)
52       .status();
53 }
54 
55 // Return a populated H4 event buffer of a type that proxy host doesn't interact
56 // with.
CreateNonInteractingToHostBuffer(H4PacketWithHci & h4_packet)57 Status CreateNonInteractingToHostBuffer(H4PacketWithHci& h4_packet) {
58   return CreateAndPopulateToHostEventWriter<emboss::InquiryCompleteEventWriter>(
59              h4_packet, emboss::EventCode::INQUIRY_COMPLETE)
60       .status();
61 }
62 
63 // ########## Examples
64 
65 // Example for docs.rst.
TEST(Example,ExampleUsage)66 TEST(Example, ExampleUsage) {
67   // Populate H4 buffer to send towards controller.
68   std::array<uint8_t, emboss::InquiryCommandView::SizeInBytes() + 1>
69       h4_array_from_host{};
70   H4PacketWithH4 h4_packet_from_host{emboss::H4PacketType::UNKNOWN,
71                                      h4_array_from_host};
72   PW_TEST_EXPECT_OK(
73       PopulateNoninteractingToControllerBuffer(h4_packet_from_host));
74 
75   // Populate H4 buffer to send towards host.
76   std::array<uint8_t, emboss::InquiryCompleteEventView::SizeInBytes() + 1>
77       hci_array_from_controller{};
78   H4PacketWithHci h4_packet_from_controller{emboss::H4PacketType::UNKNOWN,
79                                             hci_array_from_controller};
80 
81   PW_TEST_EXPECT_OK(
82       CreateNonInteractingToHostBuffer(h4_packet_from_controller));
83 
84   pw::Function<void(H4PacketWithHci && packet)> container_send_to_host_fn(
85       []([[maybe_unused]] H4PacketWithHci&& packet) {});
86 
87   pw::Function<void(H4PacketWithH4 && packet)> container_send_to_controller_fn(
88       ([]([[maybe_unused]] H4PacketWithH4&& packet) {}));
89 
90   // DOCSTAG: [pw_bluetooth_proxy-examples-basic]
91 
92 #include "pw_bluetooth_proxy/proxy_host.h"
93 
94   // Container creates ProxyHost .
95   ProxyHost proxy = ProxyHost(std::move(container_send_to_host_fn),
96                               std::move(container_send_to_controller_fn),
97                               /*le_acl_credits_to_reserve=*/2,
98                               /*br_edr_acl_credits_to_reserve=*/0);
99 
100   // Container passes H4 packets from host through proxy. Proxy will in turn
101   // call the container-provided `container_send_to_controller_fn` to pass them
102   // on to the controller. Some packets may be modified, added, or removed.
103   proxy.HandleH4HciFromHost(std::move(h4_packet_from_host));
104 
105   // Container passes H4 packets from controller through proxy. Proxy will in
106   // turn call the container-provided `container_send_to_host_fn` to pass them
107   // on to the controller. Some packets may be modified, added, or removed.
108   proxy.HandleH4HciFromController(std::move(h4_packet_from_controller));
109 
110   // DOCSTAG: [pw_bluetooth_proxy-examples-basic]
111 }
112 
113 // ########## PassthroughTest
114 
115 class PassthroughTest : public ProxyHostTest {};
116 
117 // Verify buffer is properly passed (contents unaltered and zero-copy).
TEST_F(PassthroughTest,ToControllerPassesEqualBuffer)118 TEST_F(PassthroughTest, ToControllerPassesEqualBuffer) {
119   std::array<uint8_t, emboss::InquiryCommandView::SizeInBytes() + 1> h4_arr{};
120   H4PacketWithH4 h4_packet{emboss::H4PacketType::UNKNOWN, h4_arr};
121   PW_TEST_EXPECT_OK(PopulateNoninteractingToControllerBuffer(h4_packet));
122 
123   // Struct for capturing because `pw::Function` can't fit multiple captures.
124   struct {
125     // Use a copy for comparison to catch if proxy incorrectly changes the
126     // passed buffer.
127     std::array<uint8_t, emboss::InquiryCommandView::SizeInBytes() + 1> h4_arr;
128     H4PacketWithH4* h4_packet;
129     uint8_t sends_called;
130   } send_capture = {h4_arr, &h4_packet, 0};
131 
132   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
133       [&send_capture](H4PacketWithH4&& packet) {
134         send_capture.sends_called++;
135         EXPECT_EQ(packet.GetH4Type(),
136                   emboss::H4PacketType(send_capture.h4_arr[0]));
137         EXPECT_TRUE(std::equal(send_capture.h4_packet->GetHciSpan().begin(),
138                                send_capture.h4_packet->GetHciSpan().end(),
139                                send_capture.h4_arr.begin() + 1,
140                                send_capture.h4_arr.end()));
141         // Verify no copy by verifying buffer is at the same memory location.
142         EXPECT_EQ(packet.GetHciSpan().data(),
143                   send_capture.h4_packet->GetHciSpan().data());
144       });
145 
146   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
147       []([[maybe_unused]] H4PacketWithHci&& packet) {});
148 
149   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
150                               std::move(send_to_controller_fn),
151                               /*le_acl_credits_to_reserve=*/2,
152                               /*br_edr_acl_credits_to_reserve=*/0);
153 
154   proxy.HandleH4HciFromHost(std::move(h4_packet));
155 
156   // Verify to controller callback was called.
157   EXPECT_EQ(send_capture.sends_called, 1);
158 }
159 
160 // Verify buffer is properly passed (contents unaltered and zero-copy).
TEST_F(PassthroughTest,ToHostPassesEqualBuffer)161 TEST_F(PassthroughTest, ToHostPassesEqualBuffer) {
162   std::array<uint8_t, emboss::InquiryCompleteEventView::SizeInBytes()>
163       hci_arr{};
164   H4PacketWithHci h4_packet{emboss::H4PacketType::UNKNOWN, hci_arr};
165   PW_TEST_EXPECT_OK(CreateNonInteractingToHostBuffer(h4_packet));
166 
167   // Struct for capturing because `pw::Function` can't fit multiple captures.
168   struct {
169     // Use a copy for comparison to catch if proxy incorrectly changes the
170     // passed buffer.
171     std::array<uint8_t, emboss::InquiryCompleteEventView::SizeInBytes()>
172         hci_arr;
173     H4PacketWithHci* h4_packet;
174     uint8_t sends_called;
175   } send_capture = {hci_arr, &h4_packet, 0};
176 
177   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
178       [&send_capture](H4PacketWithHci&& packet) {
179         send_capture.sends_called++;
180         EXPECT_EQ(packet.GetH4Type(), send_capture.h4_packet->GetH4Type());
181         EXPECT_TRUE(std::equal(send_capture.h4_packet->GetHciSpan().begin(),
182                                send_capture.h4_packet->GetHciSpan().end(),
183                                send_capture.h4_packet->GetHciSpan().begin(),
184                                send_capture.h4_packet->GetHciSpan().end()));
185         // Verify no copy by verifying buffer is at the same memory location.
186         EXPECT_EQ(packet.GetHciSpan().data(),
187                   send_capture.h4_packet->GetHciSpan().data());
188       });
189 
190   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
191       []([[maybe_unused]] H4PacketWithH4&& packet) {});
192 
193   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
194                               std::move(send_to_controller_fn),
195                               /*le_acl_credits_to_reserve=*/2,
196                               /*br_edr_acl_credits_to_reserve=*/0);
197 
198   proxy.HandleH4HciFromController(std::move(h4_packet));
199 
200   // Verify to controller callback was called.
201   EXPECT_EQ(send_capture.sends_called, 1);
202 }
203 
204 // Verify a command complete event (of a type that proxy doesn't act on) is
205 // properly passed (contents unaltered and zero-copy).
TEST_F(PassthroughTest,ToHostPassesEqualCommandComplete)206 TEST_F(PassthroughTest, ToHostPassesEqualCommandComplete) {
207   std::array<
208       uint8_t,
209       emboss::ReadLocalVersionInfoCommandCompleteEventWriter::SizeInBytes()>
210       hci_arr{};
211   H4PacketWithHci h4_packet{emboss::H4PacketType::UNKNOWN, hci_arr};
212   PW_TEST_ASSERT_OK_AND_ASSIGN(
213       auto view,
214       CreateAndPopulateToHostEventWriter<
215           emboss::ReadLocalVersionInfoCommandCompleteEventWriter>(
216           h4_packet, emboss::EventCode::COMMAND_COMPLETE));
217   view.command_complete().command_opcode().Write(
218       emboss::OpCode::READ_LOCAL_VERSION_INFO);
219 
220   // Struct for capturing because `pw::Function` can't fit multiple captures.
221   struct {
222     std::array<
223         uint8_t,
224         emboss::ReadLocalVersionInfoCommandCompleteEventWriter::SizeInBytes()>
225         hci_arr;
226     H4PacketWithHci* h4_packet;
227     uint8_t sends_called;
228   } send_capture = {hci_arr, &h4_packet, 0};
229 
230   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
231       [&send_capture](H4PacketWithHci&& packet) {
232         send_capture.sends_called++;
233         EXPECT_EQ(packet.GetH4Type(), send_capture.h4_packet->GetH4Type());
234         EXPECT_TRUE(std::equal(send_capture.h4_packet->GetHciSpan().begin(),
235                                send_capture.h4_packet->GetHciSpan().end(),
236                                send_capture.h4_packet->GetHciSpan().begin(),
237                                send_capture.h4_packet->GetHciSpan().end()));
238         // Verify no copy by verifying buffer is at the same memory location.
239         EXPECT_EQ(packet.GetHciSpan().data(),
240                   send_capture.h4_packet->GetHciSpan().data());
241       });
242 
243   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
244       []([[maybe_unused]] H4PacketWithH4&& packet) {});
245 
246   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
247                               std::move(send_to_controller_fn),
248                               /*le_acl_credits_to_reserve=*/2,
249                               /*br_edr_acl_credits_to_reserve=*/0);
250 
251   proxy.HandleH4HciFromController(std::move(h4_packet));
252 
253   // Verify to controller callback was called.
254   EXPECT_EQ(send_capture.sends_called, 1);
255 }
256 
257 // ########## BadPacketTest
258 // The proxy should not affect buffers it can't process (it should just pass
259 // them on).
260 
261 class BadPacketTest : public ProxyHostTest {};
262 
TEST_F(BadPacketTest,BadH4TypeToControllerIsPassedOn)263 TEST_F(BadPacketTest, BadH4TypeToControllerIsPassedOn) {
264   std::array<uint8_t, emboss::InquiryCommandView::SizeInBytes() + 1> h4_arr{};
265   H4PacketWithH4 h4_packet{emboss::H4PacketType::UNKNOWN, h4_arr};
266   PW_TEST_EXPECT_OK(PopulateNoninteractingToControllerBuffer(h4_packet));
267   // Set back to an invalid type (after
268   // PopulateNoninteractingToControllerBuffer).
269   h4_packet.SetH4Type(emboss::H4PacketType::UNKNOWN);
270 
271   // Struct for capturing because `pw::Function` can't fit multiple captures.
272   struct {
273     // Use a copy for comparison to catch if proxy incorrectly changes the
274     // passed buffer.
275     std::array<uint8_t, emboss::InquiryCommandView::SizeInBytes() + 1> h4_arr;
276     H4PacketWithH4* h4_packet;
277     uint8_t sends_called;
278   } send_capture = {h4_arr, &h4_packet, 0};
279 
280   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
281       [&send_capture](H4PacketWithH4&& packet) {
282         send_capture.sends_called++;
283         EXPECT_EQ(packet.GetH4Type(),
284                   emboss::H4PacketType(send_capture.h4_arr[0]));
285         EXPECT_TRUE(std::equal(send_capture.h4_packet->GetHciSpan().begin(),
286                                send_capture.h4_packet->GetHciSpan().end(),
287                                send_capture.h4_arr.begin() + 1,
288                                send_capture.h4_arr.end()));
289         // Verify no copy by verifying buffer is at the same memory location.
290         EXPECT_EQ(packet.GetHciSpan().data(),
291                   send_capture.h4_packet->GetHciSpan().data());
292       });
293 
294   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
295       []([[maybe_unused]] H4PacketWithHci&& packet) {});
296 
297   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
298                               std::move(send_to_controller_fn),
299                               /*le_acl_credits_to_reserve=*/2,
300                               /*br_edr_acl_credits_to_reserve=*/0);
301 
302   proxy.HandleH4HciFromHost(std::move(h4_packet));
303 
304   // Verify to controller callback was called.
305   EXPECT_EQ(send_capture.sends_called, 1);
306 }
307 
TEST_F(BadPacketTest,BadH4TypeToHostIsPassedOn)308 TEST_F(BadPacketTest, BadH4TypeToHostIsPassedOn) {
309   std::array<uint8_t, emboss::InquiryCompleteEventView::SizeInBytes()>
310       hci_arr{};
311   H4PacketWithHci h4_packet{emboss::H4PacketType::UNKNOWN, hci_arr};
312   PW_TEST_EXPECT_OK(CreateNonInteractingToHostBuffer(h4_packet));
313 
314   // Set back to an invalid type.
315   h4_packet.SetH4Type(emboss::H4PacketType::UNKNOWN);
316 
317   // Struct for capturing because `pw::Function` can't fit multiple captures.
318   struct {
319     // Use a copy for comparison to catch if proxy incorrectly changes the
320     // passed buffer.
321     std::array<uint8_t, emboss::InquiryCompleteEventView::SizeInBytes()>
322         hci_arr;
323     H4PacketWithHci* h4_packet;
324     uint8_t sends_called = 0;
325   } send_capture = {hci_arr, &h4_packet, 0};
326 
327   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
328       [&send_capture](H4PacketWithHci&& packet) {
329         send_capture.sends_called++;
330         EXPECT_EQ(packet.GetH4Type(), emboss::H4PacketType::UNKNOWN);
331         EXPECT_TRUE(std::equal(send_capture.h4_packet->GetHciSpan().begin(),
332                                send_capture.h4_packet->GetHciSpan().end(),
333                                send_capture.h4_packet->GetHciSpan().begin(),
334                                send_capture.h4_packet->GetHciSpan().end()));
335         // Verify no copy by verifying buffer is at the same memory location.
336         EXPECT_EQ(packet.GetHciSpan().data(),
337                   send_capture.h4_packet->GetHciSpan().data());
338       });
339 
340   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
341       []([[maybe_unused]] H4PacketWithH4&& packet) {});
342 
343   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
344                               std::move(send_to_controller_fn),
345                               /*le_acl_credits_to_reserve=*/2,
346                               /*br_edr_acl_credits_to_reserve=*/0);
347 
348   proxy.HandleH4HciFromController(std::move(h4_packet));
349 
350   // Verify to controller callback was called.
351   EXPECT_EQ(send_capture.sends_called, 1);
352 }
353 
TEST_F(BadPacketTest,EmptyBufferToControllerIsPassedOn)354 TEST_F(BadPacketTest, EmptyBufferToControllerIsPassedOn) {
355   std::array<uint8_t, 0> h4_arr;
356   H4PacketWithH4 h4_packet{emboss::H4PacketType::COMMAND, h4_arr};
357   // H4PacketWithH4 use the underlying h4 buffer to store type. Since its length
358   // is zero, it can't store it and will always return UNKNOWN.
359   EXPECT_EQ(h4_packet.GetH4Type(), emboss::H4PacketType::UNKNOWN);
360 
361   uint8_t sends_called = 0;
362   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
363       [&sends_called](H4PacketWithH4&& packet) {
364         sends_called++;
365         EXPECT_EQ(packet.GetH4Type(), emboss::H4PacketType::UNKNOWN);
366         EXPECT_TRUE(packet.GetHciSpan().empty());
367       });
368 
369   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
370       []([[maybe_unused]] H4PacketWithHci&& packet) {});
371 
372   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
373                               std::move(send_to_controller_fn),
374                               /*le_acl_credits_to_reserve=*/2,
375                               /*br_edr_acl_credits_to_reserve=*/0);
376 
377   proxy.HandleH4HciFromHost(std::move(h4_packet));
378 
379   // Verify callback was called.
380   EXPECT_EQ(sends_called, 1);
381 }
382 
TEST_F(BadPacketTest,EmptyBufferToHostIsPassedOn)383 TEST_F(BadPacketTest, EmptyBufferToHostIsPassedOn) {
384   std::array<uint8_t, 0> hci_arr;
385   H4PacketWithHci h4_packet{emboss::H4PacketType::EVENT, hci_arr};
386 
387   uint8_t sends_called = 0;
388   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
389       [&sends_called](H4PacketWithHci&& packet) {
390         sends_called++;
391         EXPECT_EQ(packet.GetH4Type(), emboss::H4PacketType::EVENT);
392         EXPECT_TRUE(packet.GetHciSpan().empty());
393       });
394 
395   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
396       []([[maybe_unused]] H4PacketWithH4&& packet) {});
397 
398   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
399                               std::move(send_to_controller_fn),
400                               /*le_acl_credits_to_reserve=*/2,
401                               /*br_edr_acl_credits_to_reserve=*/0);
402 
403   proxy.HandleH4HciFromController(std::move(h4_packet));
404 
405   // Verify callback was called.
406   EXPECT_EQ(sends_called, 1);
407 }
408 
TEST_F(BadPacketTest,TooShortEventToHostIsPassOn)409 TEST_F(BadPacketTest, TooShortEventToHostIsPassOn) {
410   std::array<uint8_t, emboss::InquiryCompleteEventView::SizeInBytes()>
411       valid_hci_arr{};
412   H4PacketWithHci valid_packet{emboss::H4PacketType::UNKNOWN, valid_hci_arr};
413   PW_TEST_EXPECT_OK(CreateNonInteractingToHostBuffer(valid_packet));
414 
415   // Create packet for sending whose span size is one less than a valid command
416   // complete event.
417   H4PacketWithHci h4_packet{valid_packet.GetH4Type(),
418                             valid_packet.GetHciSpan().subspan(
419                                 0, emboss::EventHeaderView::SizeInBytes() - 1)};
420 
421   // Struct for capturing because `pw::Function` can't fit multiple captures.
422   struct {
423     std::array<uint8_t, emboss::EventHeaderView::SizeInBytes() - 1> hci_arr;
424     uint8_t sends_called = 0;
425   } send_capture;
426   // Copy valid event into a short_array whose size is one less than a valid
427   // EventHeader.
428   std::copy(h4_packet.GetHciSpan().begin(),
429             h4_packet.GetHciSpan().end(),
430             send_capture.hci_arr.begin());
431   send_capture.sends_called = 0;
432 
433   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
434       [&send_capture](H4PacketWithHci&& packet) {
435         send_capture.sends_called++;
436         EXPECT_TRUE(std::equal(packet.GetHciSpan().begin(),
437                                packet.GetHciSpan().end(),
438                                send_capture.hci_arr.begin(),
439                                send_capture.hci_arr.end()));
440       });
441 
442   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
443       []([[maybe_unused]] H4PacketWithH4&& packet) {});
444 
445   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
446                               std::move(send_to_controller_fn),
447                               /*le_acl_credits_to_reserve=*/2,
448                               /*br_edr_acl_credits_to_reserve=*/0);
449 
450   proxy.HandleH4HciFromController(std::move(h4_packet));
451 
452   // Verify callback was called.
453   EXPECT_EQ(send_capture.sends_called, 1);
454 }
455 
TEST_F(BadPacketTest,TooShortCommandCompleteEventToHost)456 TEST_F(BadPacketTest, TooShortCommandCompleteEventToHost) {
457   std::array<
458       uint8_t,
459       emboss::ReadLocalVersionInfoCommandCompleteEventWriter::SizeInBytes()>
460       valid_hci_arr{};
461   H4PacketWithHci valid_packet{emboss::H4PacketType::UNKNOWN, valid_hci_arr};
462   PW_TEST_ASSERT_OK_AND_ASSIGN(
463       auto view,
464       CreateAndPopulateToHostEventWriter<
465           emboss::ReadLocalVersionInfoCommandCompleteEventWriter>(
466           valid_packet, emboss::EventCode::COMMAND_COMPLETE));
467   view.command_complete().command_opcode().Write(
468       emboss::OpCode::READ_LOCAL_VERSION_INFO);
469 
470   // Create packet for sending whose span size is one less than a valid command
471   // complete event.
472   H4PacketWithHci h4_packet{
473       valid_packet.GetH4Type(),
474       valid_packet.GetHciSpan().subspan(
475           0,
476           emboss::ReadLocalVersionInfoCommandCompleteEventWriter::
477                   SizeInBytes() -
478               1)};
479 
480   // Struct for capturing because `pw::Function` capture can't fit multiple
481   // fields .
482   struct {
483     std::array<
484         uint8_t,
485         emboss::ReadLocalVersionInfoCommandCompleteEventWriter::SizeInBytes() -
486             1>
487         hci_arr;
488     uint8_t sends_called = 0;
489   } send_capture;
490   std::copy(h4_packet.GetHciSpan().begin(),
491             h4_packet.GetHciSpan().end(),
492             send_capture.hci_arr.begin());
493   send_capture.sends_called = 0;
494 
495   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
496       [&send_capture](H4PacketWithHci&& packet) {
497         send_capture.sends_called++;
498         EXPECT_TRUE(std::equal(packet.GetHciSpan().begin(),
499                                packet.GetHciSpan().end(),
500                                send_capture.hci_arr.begin(),
501                                send_capture.hci_arr.end()));
502       });
503 
504   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
505       []([[maybe_unused]] H4PacketWithH4&& packet) {});
506 
507   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
508                               std::move(send_to_controller_fn),
509                               /*le_acl_credits_to_reserve=*/2,
510                               /*br_edr_acl_credits_to_reserve=*/0);
511 
512   proxy.HandleH4HciFromController(std::move(h4_packet));
513 
514   // Verify callback was called.
515   EXPECT_EQ(send_capture.sends_called, 1);
516 }
517 
518 // ########## ReserveLeAclCreditsTest
519 
520 class ReserveLeAclCreditsTest : public ProxyHostTest {};
521 
522 // Proxy Host should reserve requested ACL credits from controller's ACL credits
523 // when using ReadBufferSize command.
TEST_F(ReserveLeAclCreditsTest,ProxyCreditsReserveCreditsWithReadBufferSize)524 TEST_F(ReserveLeAclCreditsTest, ProxyCreditsReserveCreditsWithReadBufferSize) {
525   std::array<uint8_t,
526              emboss::ReadBufferSizeCommandCompleteEventWriter::SizeInBytes()>
527       hci_arr{};
528   H4PacketWithHci h4_packet{emboss::H4PacketType::UNKNOWN, hci_arr};
529   PW_TEST_ASSERT_OK_AND_ASSIGN(
530       auto view,
531       CreateAndPopulateToHostEventWriter<
532           emboss::ReadBufferSizeCommandCompleteEventWriter>(
533           h4_packet, emboss::EventCode::COMMAND_COMPLETE));
534   view.command_complete().command_opcode().Write(
535       emboss::OpCode::READ_BUFFER_SIZE);
536   view.total_num_acl_data_packets().Write(10);
537 
538   uint8_t sends_called = 0;
539   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
540       [&sends_called](H4PacketWithHci&& received_packet) {
541         sends_called++;
542         PW_TEST_ASSERT_OK_AND_ASSIGN(
543             auto event_view,
544             MakeEmbossWriter<emboss::ReadBufferSizeCommandCompleteEventWriter>(
545                 received_packet.GetHciSpan()));
546         // Should reserve 2 credits from original total of 10 (so 8 left for
547         // host).
548         EXPECT_EQ(event_view.total_num_acl_data_packets().Read(), 8);
549       });
550 
551   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
552       []([[maybe_unused]] H4PacketWithH4&& packet) {});
553 
554   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
555                               std::move(send_to_controller_fn),
556                               /*le_acl_credits_to_reserve=*/0,
557                               /*br_edr_acl_credits_to_reserve=*/2);
558 
559   proxy.HandleH4HciFromController(std::move(h4_packet));
560 
561   EXPECT_EQ(proxy.GetNumFreeBrEdrAclPackets(), 2);
562 
563   EXPECT_TRUE(proxy.HasSendBrEdrAclCapability());
564 
565   // Verify to controller callback was called.
566   EXPECT_EQ(sends_called, 1);
567 }
568 
569 // Proxy Host should reserve requested ACL LE credits from controller's ACL LE
570 // credits when using LEReadBufferSizeV1 command.
TEST_F(ReserveLeAclCreditsTest,ProxyCreditsReserveCreditsWithLEReadBufferSizeV1)571 TEST_F(ReserveLeAclCreditsTest,
572        ProxyCreditsReserveCreditsWithLEReadBufferSizeV1) {
573   std::array<
574       uint8_t,
575       emboss::LEReadBufferSizeV1CommandCompleteEventWriter::SizeInBytes()>
576       hci_arr{};
577   H4PacketWithHci h4_packet{emboss::H4PacketType::UNKNOWN, hci_arr};
578   PW_TEST_ASSERT_OK_AND_ASSIGN(
579       auto view,
580       CreateAndPopulateToHostEventWriter<
581           emboss::LEReadBufferSizeV1CommandCompleteEventWriter>(
582           h4_packet, emboss::EventCode::COMMAND_COMPLETE));
583   view.command_complete().command_opcode().Write(
584       emboss::OpCode::LE_READ_BUFFER_SIZE_V1);
585   view.total_num_le_acl_data_packets().Write(10);
586 
587   uint8_t sends_called = 0;
588   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
589       [&sends_called](H4PacketWithHci&& received_packet) {
590         sends_called++;
591         PW_TEST_ASSERT_OK_AND_ASSIGN(
592             auto event_view,
593             MakeEmbossView<
594                 emboss::LEReadBufferSizeV1CommandCompleteEventWriter>(
595                 received_packet.GetHciSpan()));
596 
597         // Should reserve 2 credits from original total of 10 (so 8 left for
598         // host).
599         EXPECT_EQ(event_view.total_num_le_acl_data_packets().Read(), 8);
600       });
601 
602   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
603       []([[maybe_unused]] H4PacketWithH4&& packet) {});
604 
605   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
606                               std::move(send_to_controller_fn),
607                               /*le_acl_credits_to_reserve=*/2,
608                               /*br_edr_acl_credits_to_reserve=*/0);
609 
610   proxy.HandleH4HciFromController(std::move(h4_packet));
611 
612   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 2);
613 
614   EXPECT_TRUE(proxy.HasSendLeAclCapability());
615 
616   // Verify to controller callback was called.
617   EXPECT_EQ(sends_called, 1);
618 }
619 
620 // Proxy Host should reserve requested ACL LE credits from controller's ACL LE
621 // credits when using LEReadBufferSizeV2 command.
TEST_F(ReserveLeAclCreditsTest,ProxyCreditsReserveCreditsWithLEReadBufferSizeV2)622 TEST_F(ReserveLeAclCreditsTest,
623        ProxyCreditsReserveCreditsWithLEReadBufferSizeV2) {
624   std::array<
625       uint8_t,
626       emboss::LEReadBufferSizeV2CommandCompleteEventWriter::SizeInBytes()>
627       hci_arr{};
628   H4PacketWithHci h4_packet{emboss::H4PacketType::UNKNOWN, hci_arr};
629   PW_TEST_ASSERT_OK_AND_ASSIGN(
630       auto view,
631       CreateAndPopulateToHostEventWriter<
632           emboss::LEReadBufferSizeV2CommandCompleteEventWriter>(
633           h4_packet, emboss::EventCode::COMMAND_COMPLETE));
634   view.command_complete().command_opcode().Write(
635       emboss::OpCode::LE_READ_BUFFER_SIZE_V2);
636   view.total_num_le_acl_data_packets().Write(10);
637 
638   uint8_t sends_called = 0;
639   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
640       [&sends_called](H4PacketWithHci&& received_packet) {
641         sends_called++;
642         PW_TEST_ASSERT_OK_AND_ASSIGN(
643             auto event_view,
644             MakeEmbossView<
645                 emboss::LEReadBufferSizeV2CommandCompleteEventWriter>(
646                 received_packet.GetHciSpan()));
647         // Should reserve 2 credits from original total of 10 (so 8 left for
648         // host).
649         EXPECT_EQ(event_view.total_num_le_acl_data_packets().Read(), 8);
650       });
651 
652   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
653       []([[maybe_unused]] H4PacketWithH4&& packet) {});
654 
655   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
656                               std::move(send_to_controller_fn),
657                               /*le_acl_credits_to_reserve=*/2,
658                               /*br_edr_acl_credits_to_reserve=*/0);
659 
660   proxy.HandleH4HciFromController(std::move(h4_packet));
661 
662   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 2);
663 
664   EXPECT_TRUE(proxy.HasSendLeAclCapability());
665 
666   // Verify to controller callback was called.
667   EXPECT_EQ(sends_called, 1);
668 }
669 
670 // If controller provides less than wanted credits, we should reserve that
671 // smaller amount.
TEST_F(ReserveLeAclCreditsTest,ProxyCreditsCappedByControllerCredits)672 TEST_F(ReserveLeAclCreditsTest, ProxyCreditsCappedByControllerCredits) {
673   std::array<
674       uint8_t,
675       emboss::LEReadBufferSizeV1CommandCompleteEventWriter::SizeInBytes()>
676       hci_arr{};
677   H4PacketWithHci h4_packet{emboss::H4PacketType::UNKNOWN, hci_arr};
678   PW_TEST_ASSERT_OK_AND_ASSIGN(
679       auto view,
680       CreateAndPopulateToHostEventWriter<
681           emboss::LEReadBufferSizeV1CommandCompleteEventWriter>(
682           h4_packet, emboss::EventCode::COMMAND_COMPLETE));
683   view.command_complete().command_opcode().Write(
684       emboss::OpCode::LE_READ_BUFFER_SIZE_V1);
685   view.total_num_le_acl_data_packets().Write(5);
686 
687   uint8_t sends_called = 0;
688   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
689       [&sends_called](H4PacketWithHci&& received_packet) {
690         sends_called++;
691         // We want 7, but can reserve only 5 from original 5 (so 0 left for
692         // host).
693         PW_TEST_ASSERT_OK_AND_ASSIGN(
694             auto event_view,
695             MakeEmbossView<
696                 emboss::LEReadBufferSizeV1CommandCompleteEventWriter>(
697                 received_packet.GetHciSpan()));
698         EXPECT_EQ(event_view.total_num_le_acl_data_packets().Read(), 0);
699       });
700 
701   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
702       []([[maybe_unused]] H4PacketWithH4&& packet) {});
703 
704   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
705                               std::move(send_to_controller_fn),
706                               /*le_acl_credits_to_reserve=*/7,
707                               /*br_edr_acl_credits_to_reserve=*/0);
708 
709   proxy.HandleH4HciFromController(std::move(h4_packet));
710 
711   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 5);
712 
713   // Verify to controller callback was called.
714   EXPECT_EQ(sends_called, 1);
715 }
716 
717 // Proxy Host can reserve zero credits from controller's ACL LE credits.
TEST_F(ReserveLeAclCreditsTest,ProxyCreditsReserveZeroCredits)718 TEST_F(ReserveLeAclCreditsTest, ProxyCreditsReserveZeroCredits) {
719   std::array<
720       uint8_t,
721       emboss::LEReadBufferSizeV1CommandCompleteEventWriter::SizeInBytes()>
722       hci_arr{};
723   H4PacketWithHci h4_packet{emboss::H4PacketType::UNKNOWN, hci_arr};
724   PW_TEST_ASSERT_OK_AND_ASSIGN(
725       auto view,
726       CreateAndPopulateToHostEventWriter<
727           emboss::LEReadBufferSizeV1CommandCompleteEventWriter>(
728           h4_packet, emboss::EventCode::COMMAND_COMPLETE));
729   view.command_complete().command_opcode().Write(
730       emboss::OpCode::LE_READ_BUFFER_SIZE_V1);
731   view.total_num_le_acl_data_packets().Write(10);
732 
733   uint8_t sends_called = 0;
734   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
735       [&sends_called](H4PacketWithHci&& received_packet) {
736         sends_called++;
737         PW_TEST_ASSERT_OK_AND_ASSIGN(
738             auto event_view,
739             MakeEmbossView<
740                 emboss::LEReadBufferSizeV1CommandCompleteEventWriter>(
741                 received_packet.GetHciSpan()));
742         // Should reserve 0 credits from original total of 10 (so 10 left for
743         // host).
744         EXPECT_EQ(event_view.total_num_le_acl_data_packets().Read(), 10);
745       });
746 
747   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
748       []([[maybe_unused]] H4PacketWithH4&& packet) {});
749 
750   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
751                               std::move(send_to_controller_fn),
752                               /*le_acl_credits_to_reserve=*/0,
753                               /*br_edr_acl_credits_to_reserve=*/0);
754 
755   proxy.HandleH4HciFromController(std::move(h4_packet));
756 
757   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
758 
759   EXPECT_FALSE(proxy.HasSendLeAclCapability());
760 
761   // Verify to controller callback was called.
762   EXPECT_EQ(sends_called, 1);
763 }
764 
765 // If controller has no credits, proxy should reserve none.
TEST_F(ReserveLeAclCreditsTest,ProxyCreditsZeroWhenHostCreditsZero)766 TEST_F(ReserveLeAclCreditsTest, ProxyCreditsZeroWhenHostCreditsZero) {
767   std::array<
768       uint8_t,
769       emboss::LEReadBufferSizeV1CommandCompleteEventWriter::SizeInBytes()>
770       hci_arr{};
771   H4PacketWithHci h4_packet{emboss::H4PacketType::UNKNOWN, hci_arr};
772   PW_TEST_ASSERT_OK_AND_ASSIGN(
773       auto view,
774       CreateAndPopulateToHostEventWriter<
775           emboss::LEReadBufferSizeV1CommandCompleteEventWriter>(
776           h4_packet, emboss::EventCode::COMMAND_COMPLETE));
777   view.command_complete().command_opcode().Write(
778       emboss::OpCode::LE_READ_BUFFER_SIZE_V1);
779   view.total_num_le_acl_data_packets().Write(0);
780 
781   uint8_t sends_called = 0;
782   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
783       [&sends_called](H4PacketWithHci&& received_packet) {
784         sends_called++;
785         PW_TEST_ASSERT_OK_AND_ASSIGN(
786             auto event_view,
787             MakeEmbossView<
788                 emboss::LEReadBufferSizeV1CommandCompleteEventWriter>(
789                 received_packet.GetHciSpan()));
790         // Should reserve 0 credit from original total of 0 (so 0 left for
791         // host).
792         EXPECT_EQ(event_view.total_num_le_acl_data_packets().Read(), 0);
793       });
794 
795   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
796       []([[maybe_unused]] H4PacketWithH4&& packet) {});
797 
798   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
799                               std::move(send_to_controller_fn),
800                               /*le_acl_credits_to_reserve=*/2,
801                               /*br_edr_acl_credits_to_reserve=*/0);
802 
803   proxy.HandleH4HciFromController(std::move(h4_packet));
804 
805   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
806 
807   EXPECT_TRUE(proxy.HasSendLeAclCapability());
808 
809   // Verify to controller callback was called.
810   EXPECT_EQ(sends_called, 1);
811 }
812 
TEST_F(ReserveLeAclCreditsTest,ProxyCreditsZeroWhenNotInitialized)813 TEST_F(ReserveLeAclCreditsTest, ProxyCreditsZeroWhenNotInitialized) {
814   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
815       []([[maybe_unused]] H4PacketWithHci&& packet) {});
816 
817   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
818       []([[maybe_unused]] H4PacketWithH4&& packet) {});
819 
820   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
821                               std::move(send_to_controller_fn),
822                               /*le_acl_credits_to_reserve=*/2,
823                               /*br_edr_acl_credits_to_reserve=*/0);
824 
825   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
826 
827   EXPECT_TRUE(proxy.HasSendLeAclCapability());
828 }
829 
830 // ########## NumberOfCompletedPacketsTest
831 
832 class NumberOfCompletedPacketsTest : public ProxyHostTest {};
833 
TEST_F(NumberOfCompletedPacketsTest,TwoOfThreeSentPacketsComplete)834 TEST_F(NumberOfCompletedPacketsTest, TwoOfThreeSentPacketsComplete) {
835   constexpr size_t kNumConnections = 3;
836   struct {
837     int sends_called = 0;
838     const std::array<uint16_t, kNumConnections> connection_handles = {
839         0x123, 0x456, 0x789};
840   } capture;
841 
842   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
843       [&capture](H4PacketWithHci&& packet) {
844         PW_TEST_ASSERT_OK_AND_ASSIGN(
845             auto event_header,
846             MakeEmbossView<emboss::EventHeaderView>(packet.GetHciSpan().subspan(
847                 0, emboss::EventHeader::IntrinsicSizeInBytes())));
848         capture.sends_called++;
849         if (event_header.event_code().Read() !=
850             emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS) {
851           return;
852         }
853 
854         PW_TEST_ASSERT_OK_AND_ASSIGN(
855             auto view,
856             MakeEmbossView<emboss::NumberOfCompletedPacketsEventView>(
857                 packet.GetHciSpan()));
858         EXPECT_EQ(packet.GetHciSpan().size(), 15ul);
859         EXPECT_EQ(view.num_handles().Read(), capture.connection_handles.size());
860         EXPECT_EQ(view.header().event_code().Read(),
861                   emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
862 
863         // Proxy should have reclaimed 1 credit from Connection 0 (leaving 0
864         // credits in packet), no credits from Connection 1 (meaning 0 will be
865         // unchanged), and 1 credit from Connection 2 (leaving 0).
866         EXPECT_EQ(view.nocp_data()[0].connection_handle().Read(),
867                   capture.connection_handles[0]);
868         EXPECT_EQ(view.nocp_data()[0].num_completed_packets().Read(), 0);
869 
870         EXPECT_EQ(view.nocp_data()[1].connection_handle().Read(),
871                   capture.connection_handles[1]);
872         EXPECT_EQ(view.nocp_data()[1].num_completed_packets().Read(), 0);
873 
874         EXPECT_EQ(view.nocp_data()[2].connection_handle().Read(),
875                   capture.connection_handles[2]);
876         EXPECT_EQ(view.nocp_data()[2].num_completed_packets().Read(), 0);
877       });
878   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
879       []([[maybe_unused]] H4PacketWithH4&& packet) {});
880 
881   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
882                               std::move(send_to_controller_fn),
883                               /*le_acl_credits_to_reserve=*/kNumConnections,
884                               /*br_edr_acl_credits_to_reserve=*/0);
885   PW_TEST_EXPECT_OK(
886       SendLeReadBufferResponseFromController(proxy, kNumConnections));
887   EXPECT_EQ(capture.sends_called, 1);
888 
889   std::array<uint8_t, 1> attribute_value = {0};
890 
891   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 3);
892 
893   // Send packet; num free packets should decrement.
894   {
895     GattNotifyChannel channel = BuildGattNotifyChannel(
896         proxy, {.handle = capture.connection_handles[0]});
897     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
898     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 2);
899     // Proxy host took all credits so will not pass NOCP on to host.
900     EXPECT_EQ(capture.sends_called, 1);
901   }
902 
903   // Send packet over Connection 1, which will not have a packet completed in
904   // the Number_of_Completed_Packets event.
905   {
906     GattNotifyChannel channel = BuildGattNotifyChannel(
907         proxy, {.handle = capture.connection_handles[1]});
908     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
909     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 1);
910   }
911 
912   // Send third packet; num free packets should decrement again.
913   {
914     GattNotifyChannel channel = BuildGattNotifyChannel(
915         proxy, {.handle = capture.connection_handles[2]});
916     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
917     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
918   }
919 
920   // Send Number_of_Completed_Packets event that reports 1 packet on Connection
921   // 0, 0 packets on Connection 1, and 1 packet on Connection 2. Checks in
922   // send_to_host_fn will ensure we have reclaimed 2 of 3 credits.
923   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
924       proxy,
925       FlatMap<uint16_t, uint16_t, 3>({{{capture.connection_handles[0], 1},
926                                        {capture.connection_handles[1], 0},
927                                        {capture.connection_handles[2], 1}}})));
928   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 2);
929   // Proxy host took all credits so will not pass NOCP event on to host.
930   EXPECT_EQ(capture.sends_called, 1);
931 }
932 
TEST_F(NumberOfCompletedPacketsTest,ManyMorePacketsCompletedThanPacketsPending)933 TEST_F(NumberOfCompletedPacketsTest,
934        ManyMorePacketsCompletedThanPacketsPending) {
935   constexpr size_t kNumConnections = 2;
936   struct {
937     int sends_called = 0;
938     const std::array<uint16_t, kNumConnections> connection_handles = {0x123,
939                                                                       0x456};
940   } capture;
941 
942   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
943       [&capture](H4PacketWithHci&& packet) {
944         PW_TEST_ASSERT_OK_AND_ASSIGN(
945             auto event_header,
946             MakeEmbossView<emboss::EventHeaderView>(packet.GetHciSpan().subspan(
947                 0, emboss::EventHeader::IntrinsicSizeInBytes())));
948         capture.sends_called++;
949         if (event_header.event_code().Read() !=
950             emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS) {
951           return;
952         }
953 
954         PW_TEST_ASSERT_OK_AND_ASSIGN(
955             auto view,
956             MakeEmbossView<emboss::NumberOfCompletedPacketsEventView>(
957                 packet.GetHciSpan()));
958         EXPECT_EQ(packet.GetHciSpan().size(), 11ul);
959         EXPECT_EQ(view.num_handles().Read(), capture.connection_handles.size());
960         EXPECT_EQ(view.header().event_code().Read(),
961                   emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
962 
963         // Proxy should have reclaimed 1 credit from Connection 0 (leaving
964         // 9 credits in packet) and 1 credit from Connection 2 (leaving 14).
965         EXPECT_EQ(view.nocp_data()[0].connection_handle().Read(),
966                   capture.connection_handles[0]);
967         EXPECT_EQ(view.nocp_data()[0].num_completed_packets().Read(), 9);
968 
969         EXPECT_EQ(view.nocp_data()[1].connection_handle().Read(),
970                   capture.connection_handles[1]);
971         EXPECT_EQ(view.nocp_data()[1].num_completed_packets().Read(), 14);
972       });
973   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
974       []([[maybe_unused]] H4PacketWithH4&& packet) {});
975 
976   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
977                               std::move(send_to_controller_fn),
978                               /*le_acl_credits_to_reserve=*/2,
979                               /*br_edr_acl_credits_to_reserve=*/0);
980   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 2));
981   EXPECT_EQ(capture.sends_called, 1);
982 
983   std::array<uint8_t, 1> attribute_value = {0};
984 
985   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 2);
986 
987   // Send packet over Connection 0; num free packets should decrement.
988   {
989     GattNotifyChannel channel = BuildGattNotifyChannel(
990         proxy, {.handle = capture.connection_handles[0]});
991     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
992     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 1);
993   }
994 
995   // Send packet over Connection 1; num free packets should decrement again.
996   {
997     GattNotifyChannel channel = BuildGattNotifyChannel(
998         proxy, {.handle = capture.connection_handles[1]});
999     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1000     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1001   }
1002 
1003   // Send Number_of_Completed_Packets event that reports 10 packets on
1004   // Connection 0 and 15 packets on Connection 1. Checks in send_to_host_fn
1005   // will ensure we have reclaimed exactly 2 credits, 1 from each Connection.
1006   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1007       proxy,
1008       FlatMap<uint16_t, uint16_t, 2>({{{capture.connection_handles[0], 10},
1009                                        {capture.connection_handles[1], 15}}})));
1010   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 2);
1011   EXPECT_EQ(capture.sends_called, 2);
1012 }
1013 
TEST_F(NumberOfCompletedPacketsTest,ProxyReclaimsOnlyItsUsedCredits)1014 TEST_F(NumberOfCompletedPacketsTest, ProxyReclaimsOnlyItsUsedCredits) {
1015   constexpr size_t kNumConnections = 2;
1016   struct {
1017     int sends_called = 0;
1018     const std::array<uint16_t, kNumConnections> connection_handles = {0x123,
1019                                                                       0x456};
1020   } capture;
1021 
1022   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1023       [&capture](H4PacketWithHci&& packet) {
1024         PW_TEST_ASSERT_OK_AND_ASSIGN(
1025             auto event_header,
1026             MakeEmbossView<emboss::EventHeaderView>(packet.GetHciSpan().subspan(
1027                 0, emboss::EventHeader::IntrinsicSizeInBytes())));
1028         capture.sends_called++;
1029         if (event_header.event_code().Read() !=
1030             emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS) {
1031           return;
1032         }
1033 
1034         PW_TEST_ASSERT_OK_AND_ASSIGN(
1035             auto view,
1036             MakeEmbossView<emboss::NumberOfCompletedPacketsEventView>(
1037                 packet.GetHciSpan()));
1038         EXPECT_EQ(packet.GetHciSpan().size(), 11ul);
1039         EXPECT_EQ(view.num_handles().Read(), 2);
1040         EXPECT_EQ(view.header().event_code().Read(),
1041                   emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
1042 
1043         // Proxy has 4 credits it wants to reclaim, but it should have only
1044         // reclaimed the 2 credits it used on Connection 0.
1045         EXPECT_EQ(view.nocp_data()[0].connection_handle().Read(),
1046                   capture.connection_handles[0]);
1047         EXPECT_EQ(view.nocp_data()[0].num_completed_packets().Read(), 8);
1048         EXPECT_EQ(view.nocp_data()[1].connection_handle().Read(),
1049                   capture.connection_handles[1]);
1050         EXPECT_EQ(view.nocp_data()[1].num_completed_packets().Read(), 15);
1051       });
1052   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1053       []([[maybe_unused]] H4PacketWithH4&& packet) {});
1054 
1055   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1056                               std::move(send_to_controller_fn),
1057                               /*le_acl_credits_to_reserve=*/4,
1058                               /*br_edr_acl_credits_to_reserve=*/0);
1059   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 4));
1060   EXPECT_EQ(capture.sends_called, 1);
1061 
1062   std::array<uint8_t, 1> attribute_value = {0};
1063 
1064   // Use 2 credits on Connection 0 and 2 credits on random connections that will
1065   // not be included in the NOCP event.
1066   {
1067     GattNotifyChannel channel = BuildGattNotifyChannel(
1068         proxy, {.handle = capture.connection_handles[0]});
1069     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1070     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1071   }
1072   {
1073     GattNotifyChannel channel =
1074         BuildGattNotifyChannel(proxy, {.handle = 0xABC});
1075     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1076     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1077     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1078   }
1079 
1080   // Send Number_of_Completed_Packets event that reports 10 packets on
1081   // Connection 0 and 15 packets on Connection 1. Checks in send_to_host_fn
1082   // will ensure we have reclaimed only 2 credits.
1083   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1084       proxy,
1085       FlatMap<uint16_t, uint16_t, 2>({{{capture.connection_handles[0], 10},
1086                                        {capture.connection_handles[1], 15}}})));
1087   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 2);
1088   // NOCP has credits remaining so will be passed on to host.
1089   EXPECT_EQ(capture.sends_called, 2);
1090 }
1091 
TEST_F(NumberOfCompletedPacketsTest,EventUnmodifiedIfNoCreditsInUse)1092 TEST_F(NumberOfCompletedPacketsTest, EventUnmodifiedIfNoCreditsInUse) {
1093   constexpr size_t kNumConnections = 2;
1094   struct {
1095     int sends_called = 0;
1096     const std::array<uint16_t, kNumConnections> connection_handles = {0x123,
1097                                                                       0x456};
1098   } capture;
1099 
1100   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1101       [&capture](H4PacketWithHci&& packet) {
1102         PW_TEST_ASSERT_OK_AND_ASSIGN(
1103             auto event_header,
1104             MakeEmbossView<emboss::EventHeaderView>(packet.GetHciSpan().subspan(
1105                 0, emboss::EventHeader::IntrinsicSizeInBytes())));
1106         capture.sends_called++;
1107         if (event_header.event_code().Read() !=
1108             emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS) {
1109           return;
1110         }
1111 
1112         PW_TEST_ASSERT_OK_AND_ASSIGN(
1113             auto view,
1114             MakeEmbossView<emboss::NumberOfCompletedPacketsEventView>(
1115                 packet.GetHciSpan()));
1116         EXPECT_EQ(packet.GetHciSpan().size(), 11ul);
1117         EXPECT_EQ(view.num_handles().Read(), 2);
1118         EXPECT_EQ(view.header().event_code().Read(),
1119                   emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
1120 
1121         // Event should be unmodified.
1122         EXPECT_EQ(view.nocp_data()[0].connection_handle().Read(),
1123                   capture.connection_handles[0]);
1124         EXPECT_EQ(view.nocp_data()[0].num_completed_packets().Read(), 10);
1125         EXPECT_EQ(view.nocp_data()[1].connection_handle().Read(),
1126                   capture.connection_handles[1]);
1127         EXPECT_EQ(view.nocp_data()[1].num_completed_packets().Read(), 15);
1128       });
1129   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1130       []([[maybe_unused]] H4PacketWithH4&& packet) {});
1131 
1132   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1133                               std::move(send_to_controller_fn),
1134                               /*le_acl_credits_to_reserve=*/10,
1135                               /*br_edr_acl_credits_to_reserve=*/0);
1136   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 10));
1137   EXPECT_EQ(capture.sends_called, 1);
1138 
1139   // Send Number_of_Completed_Packets event that reports 10 packets on
1140   // Connection 0 and 15 packets on Connection 1. Checks in send_to_host_fn
1141   // will ensure we have not modified the NOCP event.
1142   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1143       proxy,
1144       FlatMap<uint16_t, uint16_t, 2>({{{capture.connection_handles[0], 10},
1145                                        {capture.connection_handles[1], 15}}})));
1146   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 10);
1147   // NOCP has credits remaining so will be passed on to host.
1148   EXPECT_EQ(capture.sends_called, 2);
1149 }
1150 
TEST_F(NumberOfCompletedPacketsTest,HandlesUnusualEvents)1151 TEST_F(NumberOfCompletedPacketsTest, HandlesUnusualEvents) {
1152   constexpr size_t kNumConnections = 5;
1153   struct {
1154     int sends_called = 0;
1155     const std::array<uint16_t, kNumConnections> connection_handles = {
1156         0x123, 0x234, 0x345, 0x456, 0x567};
1157   } capture;
1158 
1159   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1160       [&capture](H4PacketWithHci&& packet) {
1161         PW_TEST_ASSERT_OK_AND_ASSIGN(
1162             auto event_header,
1163             MakeEmbossView<emboss::EventHeaderView>(packet.GetHciSpan().subspan(
1164                 0, emboss::EventHeader::IntrinsicSizeInBytes())));
1165         capture.sends_called++;
1166         if (event_header.event_code().Read() !=
1167             emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS) {
1168           return;
1169         }
1170 
1171         PW_TEST_ASSERT_OK_AND_ASSIGN(
1172             auto view,
1173             MakeEmbossView<emboss::NumberOfCompletedPacketsEventView>(
1174                 packet.GetHciSpan()));
1175         if (view.num_handles().Read() == 0) {
1176           return;
1177         }
1178 
1179         EXPECT_EQ(packet.GetHciSpan().size(), 23ul);
1180         EXPECT_EQ(view.num_handles().Read(), 5);
1181         EXPECT_EQ(view.header().event_code().Read(),
1182                   emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
1183 
1184         // Event should be unmodified.
1185         for (int i = 0; i < 5; ++i) {
1186           EXPECT_EQ(view.nocp_data()[i].connection_handle().Read(),
1187                     capture.connection_handles[i]);
1188           EXPECT_EQ(view.nocp_data()[i].num_completed_packets().Read(), 0);
1189         }
1190       });
1191   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1192       []([[maybe_unused]] H4PacketWithH4&& packet) {});
1193 
1194   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1195                               std::move(send_to_controller_fn),
1196                               /*le_acl_credits_to_reserve=*/10,
1197                               /*br_edr_acl_credits_to_reserve=*/0);
1198   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 10));
1199   EXPECT_EQ(capture.sends_called, 1);
1200 
1201   // Send Number_of_Completed_Packets event with no entries.
1202   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1203       proxy, FlatMap<uint16_t, uint16_t, 0>({{}})));
1204   // NOCP has no entries, so will not be passed on to host.
1205   EXPECT_EQ(capture.sends_called, 1);
1206 
1207   // Send Number_of_Completed_Packets event that reports 0 packets for various
1208   // connections.
1209   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1210       proxy,
1211       FlatMap<uint16_t, uint16_t, 5>({{{capture.connection_handles[0], 0},
1212                                        {capture.connection_handles[1], 0},
1213                                        {capture.connection_handles[2], 0},
1214                                        {capture.connection_handles[3], 0},
1215                                        {capture.connection_handles[4], 0}}})));
1216   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 10);
1217   // Proxy host will not pass on a NOCP with no credits.
1218   EXPECT_EQ(capture.sends_called, 1);
1219 }
1220 
TEST_F(NumberOfCompletedPacketsTest,MultipleChannelsDifferentTransports)1221 TEST_F(NumberOfCompletedPacketsTest, MultipleChannelsDifferentTransports) {
1222   static constexpr size_t kPayloadSize = 3;
1223   struct {
1224     int sends_called = 0;
1225     std::array<uint8_t, kPayloadSize> payload = {
1226         0xAB,
1227         0xCD,
1228         0xEF,
1229     };
1230   } capture;
1231 
1232   pw::Function<void(H4PacketWithHci&&)>&& send_to_host_fn(
1233       [](H4PacketWithHci&&) {});
1234   pw::Function<void(H4PacketWithH4&&)>&& send_to_controller_fn(
1235       [&capture](H4PacketWithH4&&) { ++capture.sends_called; });
1236 
1237   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1238                               std::move(send_to_controller_fn),
1239                               /*le_acl_credits_to_reserve=*/1,
1240                               /*br_edr_acl_credits_to_reserve=*/1);
1241   // Allow proxy to reserve BR/EDR 1 credit.
1242   PW_TEST_EXPECT_OK(SendReadBufferResponseFromController(proxy, 1));
1243   // Allow proxy to reserve LE 1 credit.
1244   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
1245 
1246   // Test that sending on one type of transport doesn't get blocked if the other
1247   // type of transport is out of credits.
1248 
1249   L2capCoc le_channel =
1250       BuildCoc(proxy, CocParameters{.handle = 0x123, .tx_credits = 2});
1251   PW_TEST_EXPECT_OK(le_channel.Write(multibuf::MultiBuf{}).status);
1252   EXPECT_EQ(capture.sends_called, 1);
1253 
1254   RfcommChannel bredr_channel =
1255       BuildRfcomm(proxy, RfcommParameters{.handle = 0x456});
1256   PW_TEST_EXPECT_OK(
1257       bredr_channel.Write(MultiBufFromSpan(pw::span(capture.payload))).status);
1258   // Send should succeed even though no LE credits available
1259   EXPECT_EQ(capture.sends_called, 2);
1260 
1261   // Queue an LE write
1262   PW_TEST_EXPECT_OK(le_channel.Write(multibuf::MultiBuf{}).status);
1263   EXPECT_EQ(capture.sends_called, 2);
1264 
1265   // Complete previous LE write
1266   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1267       proxy, FlatMap<uint16_t, uint16_t, 1>({{{0x123, 1}}})));
1268   EXPECT_EQ(capture.sends_called, 3);
1269 
1270   // Complete BR/EDR write
1271   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1272       proxy, FlatMap<uint16_t, uint16_t, 1>({{{0x456, 1}}})));
1273 
1274   // Write again
1275   PW_TEST_EXPECT_OK(
1276       bredr_channel.Write(MultiBufFromSpan(pw::span(capture.payload))).status);
1277   EXPECT_EQ(capture.sends_called, 4);
1278 }
1279 
1280 // ########## DisconnectionCompleteTest
1281 
1282 class DisconnectionCompleteTest : public ProxyHostTest {};
1283 
TEST_F(DisconnectionCompleteTest,DisconnectionReclaimsCredits)1284 TEST_F(DisconnectionCompleteTest, DisconnectionReclaimsCredits) {
1285   struct {
1286     int sends_called = 0;
1287     uint16_t connection_handle = 0x123;
1288   } capture;
1289 
1290   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1291       [&capture](H4PacketWithHci&& packet) {
1292         PW_TEST_ASSERT_OK_AND_ASSIGN(
1293             auto event_header,
1294             MakeEmbossView<emboss::EventHeaderView>(packet.GetHciSpan().subspan(
1295                 0, emboss::EventHeader::IntrinsicSizeInBytes())));
1296         capture.sends_called++;
1297         if (event_header.event_code().Read() !=
1298             emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS) {
1299           return;
1300         }
1301 
1302         PW_TEST_ASSERT_OK_AND_ASSIGN(
1303             auto view,
1304             MakeEmbossView<emboss::NumberOfCompletedPacketsEventView>(
1305                 packet.GetHciSpan()));
1306         EXPECT_EQ(packet.GetHciSpan().size(), 7ul);
1307         EXPECT_EQ(view.num_handles().Read(), 1);
1308         EXPECT_EQ(view.header().event_code().Read(),
1309                   emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
1310 
1311         // Event should be unmodified.
1312         EXPECT_EQ(view.nocp_data()[0].connection_handle().Read(),
1313                   capture.connection_handle);
1314         EXPECT_EQ(view.nocp_data()[0].num_completed_packets().Read(), 10);
1315       });
1316   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1317       []([[maybe_unused]] H4PacketWithH4&& packet) {});
1318 
1319   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1320                               std::move(send_to_controller_fn),
1321                               /*le_acl_credits_to_reserve=*/10,
1322                               /*br_edr_acl_credits_to_reserve=*/0);
1323   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 10));
1324   EXPECT_EQ(capture.sends_called, 1);
1325 
1326   std::array<uint8_t, 1> attribute_value = {0};
1327 
1328   {
1329     GattNotifyChannel channel =
1330         BuildGattNotifyChannel(proxy, {.handle = capture.connection_handle});
1331 
1332     // Use up 3 of the 10 credits on the Connection that will be disconnected.
1333     for (int i = 0; i < 3; ++i) {
1334       EXPECT_TRUE(
1335           channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1336     }
1337     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 7);
1338   }
1339 
1340   // Use up 2 credits on a random Connection.
1341   {
1342     GattNotifyChannel channel = BuildGattNotifyChannel(proxy, {});
1343 
1344     for (int i = 0; i < 2; ++i) {
1345       EXPECT_TRUE(
1346           channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1347     }
1348     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 5);
1349   }
1350 
1351   // Send Disconnection_Complete event, which should reclaim 3 credits.
1352   PW_TEST_EXPECT_OK(
1353       SendDisconnectionCompleteEvent(proxy, capture.connection_handle));
1354   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 8);
1355 
1356   // Use 1 credit and reclaim it on a bunch of random channels. Then send
1357   // disconnect and ensure it was cleaned up in connections list. The send will
1358   // fail if disconnect doesn't cleanup properly.
1359   //
1360   // We already have an active connection at this point in the test, so loop
1361   // over the remaining slots + 1 which would otherwise fail if cleanup wasn't
1362   // working right.
1363   for (uint16_t i = 0; i < ProxyHost::GetMaxNumAclConnections() - 2; ++i) {
1364     uint16_t handle = 0x234 + i;
1365     GattNotifyChannel channel =
1366         BuildGattNotifyChannel(proxy, {.handle = handle});
1367     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1368     PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1369         proxy, FlatMap<uint16_t, uint16_t, 1>({{{handle, 1}}})));
1370     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 8);
1371     PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(proxy, handle));
1372   }
1373 
1374   // Send Number_of_Completed_Packets event that reports 10 packets, none of
1375   // which should be reclaimed because this Connection has disconnected. Checks
1376   // in send_to_host_fn will ensure we have not modified the NOCP event.
1377   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1378       proxy,
1379       FlatMap<uint16_t, uint16_t, 1>({{{capture.connection_handle, 10}}})));
1380   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 8);
1381   // NOCP has credits remaining so will be passed on to host.
1382   EXPECT_EQ(capture.sends_called, 11);
1383 }
1384 
TEST_F(DisconnectionCompleteTest,FailedDisconnectionHasNoEffect)1385 TEST_F(DisconnectionCompleteTest, FailedDisconnectionHasNoEffect) {
1386   uint16_t connection_handle = 0x123;
1387 
1388   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1389       []([[maybe_unused]] H4PacketWithHci&& packet) {});
1390   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1391       []([[maybe_unused]] H4PacketWithH4&& packet) {});
1392 
1393   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1394                               std::move(send_to_controller_fn),
1395                               /*le_acl_credits_to_reserve=*/1,
1396                               /*br_edr_acl_credits_to_reserve=*/0);
1397   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
1398 
1399   std::array<uint8_t, 1> attribute_value = {0};
1400 
1401   // Use sole credit.
1402   GattNotifyChannel channel =
1403       BuildGattNotifyChannel(proxy, {.handle = connection_handle});
1404   EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1405   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1406 
1407   // Send failed Disconnection_Complete event, should not reclaim credit.
1408   PW_TEST_EXPECT_OK(
1409       SendDisconnectionCompleteEvent(proxy,
1410                                      connection_handle,
1411                                      /*direction=*/Direction::kFromController,
1412                                      /*successful=*/false));
1413   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1414 }
1415 
TEST_F(DisconnectionCompleteTest,DisconnectionOfUnusedConnectionHasNoEffect)1416 TEST_F(DisconnectionCompleteTest, DisconnectionOfUnusedConnectionHasNoEffect) {
1417   uint16_t connection_handle = 0x123;
1418 
1419   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1420       []([[maybe_unused]] H4PacketWithHci&& packet) {});
1421   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1422       []([[maybe_unused]] H4PacketWithH4&& packet) {});
1423 
1424   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1425                               std::move(send_to_controller_fn),
1426                               /*le_acl_credits_to_reserve=*/1,
1427                               /*br_edr_acl_credits_to_reserve=*/0);
1428   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
1429 
1430   std::array<uint8_t, 1> attribute_value = {0};
1431 
1432   // Use sole credit.
1433   GattNotifyChannel channel =
1434       BuildGattNotifyChannel(proxy, {.handle = connection_handle});
1435   EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1436   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1437 
1438   // Send Disconnection_Complete event to random Connection, should have no
1439   // effect.
1440   PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(proxy, 0x456));
1441   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1442 }
1443 
TEST_F(DisconnectionCompleteTest,CanReuseConnectionHandleAfterDisconnection)1444 TEST_F(DisconnectionCompleteTest, CanReuseConnectionHandleAfterDisconnection) {
1445   struct {
1446     int sends_called = 0;
1447     uint16_t connection_handle = 0x123;
1448   } capture;
1449 
1450   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1451       [&capture](H4PacketWithHci&& packet) {
1452         PW_TEST_ASSERT_OK_AND_ASSIGN(
1453             auto event_header,
1454             MakeEmbossView<emboss::EventHeaderView>(packet.GetHciSpan().subspan(
1455                 0, emboss::EventHeader::IntrinsicSizeInBytes())));
1456         capture.sends_called++;
1457         if (event_header.event_code().Read() !=
1458             emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS) {
1459           return;
1460         }
1461 
1462         PW_TEST_ASSERT_OK_AND_ASSIGN(
1463             auto view,
1464             MakeEmbossView<emboss::NumberOfCompletedPacketsEventView>(
1465                 packet.GetHciSpan()));
1466         EXPECT_EQ(packet.GetHciSpan().size(), 7ul);
1467         EXPECT_EQ(view.num_handles().Read(), 1);
1468         EXPECT_EQ(view.header().event_code().Read(),
1469                   emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
1470 
1471         // Should have reclaimed the 1 packet.
1472         EXPECT_EQ(view.nocp_data()[0].connection_handle().Read(),
1473                   capture.connection_handle);
1474         EXPECT_EQ(view.nocp_data()[0].num_completed_packets().Read(), 0);
1475       });
1476   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1477       []([[maybe_unused]] H4PacketWithH4&& packet) {});
1478 
1479   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1480                               std::move(send_to_controller_fn),
1481                               /*le_acl_credits_to_reserve=*/1,
1482                               /*br_edr_acl_credits_to_reserve=*/0);
1483   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
1484   EXPECT_EQ(capture.sends_called, 1);
1485 
1486   std::array<uint8_t, 1> attribute_value = {0};
1487 
1488   {
1489     // Establish connection over `connection_handle`.
1490     GattNotifyChannel channel =
1491         BuildGattNotifyChannel(proxy, {.handle = capture.connection_handle});
1492     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1493     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1494   }
1495 
1496   // Disconnect `connection_handle`.
1497   PW_TEST_EXPECT_OK(
1498       SendDisconnectionCompleteEvent(proxy, capture.connection_handle));
1499   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 1);
1500   EXPECT_EQ(capture.sends_called, 2);
1501 
1502   {
1503     // Re-establish connection over `connection_handle`.
1504     GattNotifyChannel channel =
1505         BuildGattNotifyChannel(proxy, {.handle = capture.connection_handle});
1506     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1507     EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1508   }
1509 
1510   // Send Number_of_Completed_Packets event that reports 1 packet. Checks in
1511   // send_to_host_fn will ensure packet has been reclaimed.
1512   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1513       proxy,
1514       FlatMap<uint16_t, uint16_t, 1>({{{capture.connection_handle, 1}}})));
1515   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 1);
1516   // Since proxy reclaimed the one credit, it does not pass event on to host.
1517   EXPECT_EQ(capture.sends_called, 2);
1518 }
1519 
TEST_F(DisconnectionCompleteTest,DisconnectionErasesAclConnection)1520 TEST_F(DisconnectionCompleteTest, DisconnectionErasesAclConnection) {
1521   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1522       [](H4PacketWithHci&&) {});
1523   int sends_called = 0;
1524   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1525       [&sends_called](H4PacketWithH4&&) { ++sends_called; });
1526   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1527                               std::move(send_to_controller_fn),
1528                               /*le_acl_credits_to_reserve=*/1,
1529                               /*br_edr_acl_credits_to_reserve=*/0);
1530   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
1531 
1532   uint16_t connection_handle = 0x567;
1533   pw::Vector<L2capCoc, ProxyHost::GetMaxNumAclConnections()> channels;
1534   for (size_t i = 0; i < ProxyHost::GetMaxNumAclConnections(); ++i) {
1535     channels.push_back(
1536         BuildCoc(proxy, CocParameters{.handle = ++connection_handle}));
1537   }
1538   EXPECT_EQ(
1539       BuildCocWithResult(
1540           proxy,
1541           CocParameters{.handle = static_cast<uint16_t>(connection_handle + 1)})
1542           .status(),
1543       Status::Unavailable());
1544 
1545   PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(proxy, connection_handle++));
1546   // After erasing the last ACL connection, there should be space for a new one.
1547   PW_TEST_ASSERT_OK_AND_ASSIGN(
1548       L2capCoc channel,
1549       BuildCocWithResult(proxy, CocParameters{.handle = connection_handle}));
1550   // Confirm signaling channels are functional.
1551   PW_TEST_EXPECT_OK(channel.SendAdditionalRxCredits(3));
1552   EXPECT_EQ(sends_called, 1);
1553   channels.clear();
1554 }
1555 
1556 // ########## DestructionTest
1557 
1558 class DestructionTest : public ProxyHostTest {};
1559 
1560 // This test can deadlock on failure.
TEST_F(DestructionTest,CanDestructWhenPacketsQueuedInSignalingChannel)1561 TEST_F(DestructionTest, CanDestructWhenPacketsQueuedInSignalingChannel) {
1562   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
1563       [](H4PacketWithHci&&) {});
1564   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
1565       [](H4PacketWithH4&&) {});
1566   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1567                               std::move(send_to_controller_fn),
1568                               /*le_acl_credits_to_reserve=*/0,
1569                               /*br_edr_acl_credits_to_reserve=*/0);
1570 
1571   L2capCoc channel = BuildCoc(proxy, CocParameters{.handle = 0x111});
1572   L2capCoc channel2 = BuildCoc(proxy, CocParameters{.handle = 0x222});
1573 
1574   PW_TEST_EXPECT_OK(channel.SendAdditionalRxCredits(1));
1575 }
1576 
TEST_F(DestructionTest,ChannelsStopOnProxyDestruction)1577 TEST_F(DestructionTest, ChannelsStopOnProxyDestruction) {
1578   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
1579       [](H4PacketWithHci&&) {});
1580   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
1581       [](H4PacketWithH4&&) {});
1582   size_t events_received = 0;
1583 
1584   pw::Vector<ProxyHost, 1> proxy;
1585   proxy.emplace_back(std::move(send_to_host_fn),
1586                      std::move(send_to_controller_fn),
1587                      /*le_acl_credits_to_reserve=*/0,
1588                      /*br_edr_acl_credits_to_reserve=*/0);
1589 
1590   // This event function will be called by each of the channels' event
1591   // functions.
1592   ChannelEventCallback shared_event_fn =
1593       [&events_received](L2capChannelEvent event) {
1594         ++events_received;
1595         EXPECT_EQ(event, L2capChannelEvent::kChannelClosedByOther);
1596       };
1597 
1598   BasicL2capChannel close_first_channel = BuildBasicL2capChannel(
1599       proxy.front(),
1600       BasicL2capParameters{
1601           .event_fn = [&shared_event_fn](L2capChannelEvent event) {
1602             shared_event_fn(event);
1603           }});
1604 
1605   OneOfEachChannel channel_struct =
1606       BuildOneOfEachChannel(proxy.front(), shared_event_fn);
1607 
1608   // Channel already closed before Proxy destruction should not be affected.
1609   close_first_channel.Close();
1610   EXPECT_EQ(events_received, 1ul);
1611   EXPECT_EQ(close_first_channel.state(), L2capChannel::State::kClosed);
1612 
1613   // Proxy dtor should result in close event for each of
1614   // the previously still open channels (and they should now be closed).
1615   proxy.clear();
1616   EXPECT_EQ(events_received, 1 + channel_struct.AllChannels().size());
1617   for (L2capChannel* channel : channel_struct.AllChannels()) {
1618     EXPECT_EQ(channel->state(), L2capChannel::State::kClosed);
1619   }
1620 
1621   // And first channel should remain closed of course.
1622   EXPECT_EQ(close_first_channel.state(), L2capChannel::State::kClosed);
1623 }
1624 
1625 // ########## ResetTest
1626 
1627 class ResetTest : public ProxyHostTest {};
1628 
TEST_F(ResetTest,ResetClearsActiveConnections)1629 TEST_F(ResetTest, ResetClearsActiveConnections) {
1630   struct {
1631     int sends_called = 0;
1632     const uint16_t connection_handle = 0x123;
1633   } host_capture;
1634   struct {
1635     int sends_called = 0;
1636     const uint16_t connection_handle = 0x123;
1637   } controller_capture;
1638 
1639   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1640       [&host_capture](H4PacketWithHci&& packet) {
1641         PW_TEST_ASSERT_OK_AND_ASSIGN(
1642             auto event_header,
1643             MakeEmbossView<emboss::EventHeaderView>(packet.GetHciSpan().subspan(
1644                 0, emboss::EventHeader::IntrinsicSizeInBytes())));
1645         host_capture.sends_called++;
1646         if (event_header.event_code().Read() !=
1647             emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS) {
1648           return;
1649         }
1650 
1651         PW_TEST_ASSERT_OK_AND_ASSIGN(
1652             auto view,
1653             MakeEmbossView<emboss::NumberOfCompletedPacketsEventView>(
1654                 packet.GetHciSpan()));
1655         EXPECT_EQ(packet.GetHciSpan().size(), 7ul);
1656         EXPECT_EQ(view.num_handles().Read(), 1);
1657         EXPECT_EQ(view.header().event_code().Read(),
1658                   emboss::EventCode::NUMBER_OF_COMPLETED_PACKETS);
1659 
1660         // Should be unchanged.
1661         EXPECT_EQ(view.nocp_data()[0].connection_handle().Read(),
1662                   host_capture.connection_handle);
1663         EXPECT_EQ(view.nocp_data()[0].num_completed_packets().Read(), 1);
1664       });
1665   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1666       [&controller_capture]([[maybe_unused]] H4PacketWithH4&& packet) {
1667         ++controller_capture.sends_called;
1668       });
1669 
1670   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1671                               std::move(send_to_controller_fn),
1672                               /*le_acl_credits_to_reserve=*/2,
1673                               /*br_edr_acl_credits_to_reserve=*/0);
1674   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 2));
1675   EXPECT_EQ(host_capture.sends_called, 1);
1676 
1677   std::array<uint8_t, 1> attribute_value = {0};
1678 
1679   {
1680     GattNotifyChannel channel = BuildGattNotifyChannel(
1681         proxy, {.handle = controller_capture.connection_handle});
1682     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1683     EXPECT_EQ(controller_capture.sends_called, 1);
1684   }
1685 
1686   proxy.Reset();
1687 
1688   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1689   // Reset should not have cleared `le_acl_credits_to_reserve`, so proxy should
1690   // still indicate the capability.
1691   EXPECT_TRUE(proxy.HasSendLeAclCapability());
1692 
1693   // Re-initialize AclDataChannel with 2 credits.
1694   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 2));
1695   EXPECT_EQ(host_capture.sends_called, 2);
1696 
1697   {
1698     // Send ACL on random handle to expend one credit.
1699     GattNotifyChannel channel = BuildGattNotifyChannel(proxy, {});
1700     EXPECT_TRUE(channel.Write(MultiBufFromArray(attribute_value)).status.ok());
1701     EXPECT_EQ(controller_capture.sends_called, 2);
1702   }
1703 
1704   // This should have no effect, as the reset has cleared our active connection
1705   // on this handle.
1706   PW_TEST_EXPECT_OK(SendNumberOfCompletedPackets(
1707       proxy,
1708       FlatMap<uint16_t, uint16_t, 1>({{{host_capture.connection_handle, 1}}})));
1709   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 1);
1710   // NOCP has credits remaining so will be passed on to host.
1711   EXPECT_EQ(host_capture.sends_called, 3);
1712 }
1713 
TEST_F(ResetTest,ChannelsCloseOnReset)1714 TEST_F(ResetTest, ChannelsCloseOnReset) {
1715   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
1716       [](H4PacketWithHci&&) {});
1717   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
1718       [](H4PacketWithH4&&) {});
1719   size_t events_received = 0;
1720   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1721                               std::move(send_to_controller_fn),
1722                               /*le_acl_credits_to_reserve=*/0,
1723                               /*br_edr_acl_credits_to_reserve=*/0);
1724 
1725   // This event function will be called by each of the channels' event
1726   // functions.
1727   ChannelEventCallback shared_event_fn =
1728       [&events_received](L2capChannelEvent event) {
1729         if (++events_received == 1) {
1730           EXPECT_EQ(event, L2capChannelEvent::kChannelClosedByOther);
1731         } else {
1732           EXPECT_EQ(event, L2capChannelEvent::kReset);
1733         }
1734       };
1735 
1736   BasicL2capChannel close_first_channel = BuildBasicL2capChannel(
1737       proxy,
1738       BasicL2capParameters{
1739           .event_fn = [&shared_event_fn](L2capChannelEvent event) {
1740             shared_event_fn(event);
1741           }});
1742 
1743   OneOfEachChannel channel_struct =
1744       BuildOneOfEachChannel(proxy, shared_event_fn);
1745 
1746   // Channel already closed before Proxy reset should not be affected.
1747   close_first_channel.Close();
1748   EXPECT_EQ(events_received, 1ul);
1749   EXPECT_EQ(close_first_channel.state(), L2capChannel::State::kClosed);
1750 
1751   // Proxy reset should result in close event for each of
1752   // the previously still open channels (and they should now be closed).
1753   proxy.Reset();
1754   EXPECT_EQ(events_received, 1 + channel_struct.AllChannels().size());
1755   for (L2capChannel* channel : channel_struct.AllChannels()) {
1756     EXPECT_EQ(channel->state(), L2capChannel::State::kClosed);
1757   }
1758 
1759   // And first channel should remain closed of course.
1760   EXPECT_EQ(close_first_channel.state(), L2capChannel::State::kClosed);
1761 }
1762 
TEST_F(ResetTest,ProxyHandlesMultipleResets)1763 TEST_F(ResetTest, ProxyHandlesMultipleResets) {
1764   int sends_called = 0;
1765 
1766   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
1767       []([[maybe_unused]] H4PacketWithHci&& packet) {});
1768   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1769       [&sends_called]([[maybe_unused]] H4PacketWithH4&& packet) {
1770         ++sends_called;
1771       });
1772 
1773   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1774                               std::move(send_to_controller_fn),
1775                               /*le_acl_credits_to_reserve=*/1,
1776                               /*br_edr_acl_credits_to_reserve=*/0);
1777   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
1778 
1779   proxy.Reset();
1780   proxy.Reset();
1781 
1782   std::array<uint8_t, 1> attribute_value = {0};
1783   // Validate state after double reset.
1784   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1785   EXPECT_TRUE(proxy.HasSendLeAclCapability());
1786   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
1787   {
1788     GattNotifyChannel channel = BuildGattNotifyChannel(proxy, {});
1789     EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1790               PW_STATUS_OK);
1791   }
1792   EXPECT_EQ(sends_called, 1);
1793 
1794   proxy.Reset();
1795 
1796   // Validate state after third reset.
1797   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 0);
1798   EXPECT_TRUE(proxy.HasSendLeAclCapability());
1799   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
1800   {
1801     GattNotifyChannel channel = BuildGattNotifyChannel(proxy, {});
1802     EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1803               PW_STATUS_OK);
1804   }
1805   EXPECT_EQ(sends_called, 2);
1806 }
1807 
TEST_F(ResetTest,HandleHciReset)1808 TEST_F(ResetTest, HandleHciReset) {
1809   struct {
1810     int sends_called = 0;
1811     const uint16_t connection_handle = 0x123;
1812   } host_capture;
1813   struct {
1814     int sends_called = 0;
1815     const uint16_t connection_handle = 0x123;
1816   } controller_capture;
1817 
1818   pw::Function<void(H4PacketWithHci&&)> send_to_host_fn(
1819       [&host_capture](H4PacketWithHci&&) { ++host_capture.sends_called; });
1820   pw::Function<void(H4PacketWithH4&&)> send_to_controller_fn(
1821       [&controller_capture](H4PacketWithH4&&) {
1822         ++controller_capture.sends_called;
1823       });
1824 
1825   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1826                               std::move(send_to_controller_fn),
1827                               /*le_acl_credits_to_reserve=*/2,
1828                               /*br_edr_acl_credits_to_reserve=*/0);
1829   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 2));
1830   EXPECT_EQ(host_capture.sends_called, 1);
1831 
1832   // Use 1 credit.
1833   std::array<uint8_t, 1> attribute_value = {0};
1834   GattNotifyChannel channel = BuildGattNotifyChannel(
1835       proxy, {.handle = controller_capture.connection_handle});
1836   EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1837             PW_STATUS_OK);
1838   EXPECT_EQ(controller_capture.sends_called, 1);
1839   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 1);
1840 
1841   // Send HCI_Reset. This should cause proxy to reset and our free credits as
1842   // well.
1843   std::array<uint8_t, emboss::ResetCommandView::SizeInBytes() + 1>
1844       h4_array_from_host{};
1845   H4PacketWithH4 h4_packet_from_host{emboss::H4PacketType::UNKNOWN,
1846                                      h4_array_from_host};
1847   PW_TEST_EXPECT_OK(
1848       CreateAndPopulateToControllerView<emboss::ResetCommandWriter>(
1849           h4_packet_from_host,
1850           emboss::OpCode::RESET,
1851           /*parameter_total_size=*/0));
1852   proxy.HandleH4HciFromHost(std::move(h4_packet_from_host));
1853 
1854   // Send new buffer response which shouldn't crash.
1855   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 2));
1856   EXPECT_EQ(host_capture.sends_called, 2);
1857   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), 2);
1858 }
1859 
1860 // ########## MultiSendTest
1861 
1862 class MultiSendTest : public ProxyHostTest {};
1863 
TEST_F(MultiSendTest,CanOccupyAllThenReuseEachBuffer)1864 TEST_F(MultiSendTest, CanOccupyAllThenReuseEachBuffer) {
1865   constexpr size_t kMaxSends = ProxyHost::GetNumSimultaneousAclSendsSupported();
1866   struct {
1867     size_t sends_called = 0;
1868     std::array<H4PacketWithH4, 2 * kMaxSends> released_packets{};
1869   } capture;
1870 
1871   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
1872       []([[maybe_unused]] H4PacketWithHci&& packet) {});
1873   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1874       [&capture](H4PacketWithH4&& packet) {
1875         // Capture all packets to prevent their destruction.
1876         capture.released_packets[capture.sends_called++] = std::move(packet);
1877       });
1878 
1879   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1880                               std::move(send_to_controller_fn),
1881                               /*le_acl_credits_to_reserve=*/2 * kMaxSends,
1882                               /*br_edr_acl_credits_to_reserve=*/0);
1883   // Allow proxy to reserve enough credits to send twice the number of
1884   // simultaneous sends supported by proxy.
1885   PW_TEST_EXPECT_OK(
1886       SendLeReadBufferResponseFromController(proxy, 2 * kMaxSends));
1887 
1888   GattNotifyChannel channel = BuildGattNotifyChannel(proxy, {});
1889 
1890   std::array<uint8_t, 1> attribute_value = {0xF};
1891   // Occupy all send buffers.
1892   for (size_t i = 0; i < kMaxSends; ++i) {
1893     EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1894               PW_STATUS_OK);
1895   }
1896   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), kMaxSends);
1897   EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1898             PW_STATUS_UNAVAILABLE);
1899 
1900   // Confirm we can release and reoccupy each buffer slot.
1901   for (size_t i = 0; i < kMaxSends; ++i) {
1902     capture.released_packets[i].~H4PacketWithH4();
1903     EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1904               PW_STATUS_OK);
1905     EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1906               PW_STATUS_UNAVAILABLE);
1907   }
1908   EXPECT_EQ(capture.sends_called, 2 * kMaxSends);
1909 
1910   // If captured packets are not reset here, they may destruct after the proxy
1911   // and lead to a crash when trying to lock the proxy's destructed mutex.
1912   for (auto& packet : capture.released_packets) {
1913     packet.ResetAndReturnReleaseFn();
1914   }
1915 }
1916 
TEST_F(MultiSendTest,CanRepeatedlyReuseOneBuffer)1917 TEST_F(MultiSendTest, CanRepeatedlyReuseOneBuffer) {
1918   constexpr size_t kMaxSends = ProxyHost::GetNumSimultaneousAclSendsSupported();
1919   struct {
1920     size_t sends_called = 0;
1921     std::array<H4PacketWithH4, kMaxSends> released_packets{};
1922   } capture;
1923 
1924   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
1925       []([[maybe_unused]] H4PacketWithHci&& packet) {});
1926   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1927       [&capture](H4PacketWithH4&& packet) {
1928         // Capture first kMaxSends packets linearly.
1929         if (capture.sends_called < capture.released_packets.size()) {
1930           capture.released_packets[capture.sends_called] = std::move(packet);
1931         } else {
1932           // Reuse only first packet slot after kMaxSends.
1933           capture.released_packets[0] = std::move(packet);
1934         }
1935         ++capture.sends_called;
1936       });
1937 
1938   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1939                               std::move(send_to_controller_fn),
1940                               /*le_acl_credits_to_reserve=*/2 * kMaxSends,
1941                               /*br_edr_acl_credits_to_reserve=*/0);
1942   PW_TEST_EXPECT_OK(
1943       SendLeReadBufferResponseFromController(proxy, 2 * kMaxSends));
1944 
1945   GattNotifyChannel channel = BuildGattNotifyChannel(proxy, {});
1946 
1947   std::array<uint8_t, 1> attribute_value = {0xF};
1948   // Occupy all send buffers.
1949   for (size_t i = 0; i < kMaxSends; ++i) {
1950     EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1951               PW_STATUS_OK);
1952   }
1953 
1954   // Repeatedly free and reoccupy first buffer.
1955   for (size_t i = 0; i < kMaxSends; ++i) {
1956     capture.released_packets[0].~H4PacketWithH4();
1957     EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1958               PW_STATUS_OK);
1959     EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1960               PW_STATUS_UNAVAILABLE);
1961   }
1962   EXPECT_EQ(capture.sends_called, 2 * kMaxSends);
1963 
1964   // If captured packets are not reset here, they may destruct after the proxy
1965   // and lead to a crash when trying to lock the proxy's destructed mutex.
1966   for (auto& packet : capture.released_packets) {
1967     packet.ResetAndReturnReleaseFn();
1968   }
1969 }
1970 
TEST_F(MultiSendTest,CanSendOverManyDifferentConnections)1971 TEST_F(MultiSendTest, CanSendOverManyDifferentConnections) {
1972   std::array<uint8_t, 1> attribute_value = {0xF};
1973   struct {
1974     uint16_t sends_called = 0;
1975   } capture;
1976 
1977   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
1978       []([[maybe_unused]] H4PacketWithHci&& packet) {});
1979   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
1980       [&capture]([[maybe_unused]] H4PacketWithH4&& packet) {
1981         ++capture.sends_called;
1982       });
1983 
1984   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
1985                               std::move(send_to_controller_fn),
1986                               ProxyHost::GetMaxNumAclConnections(),
1987                               /*br_edr_acl_credits_to_reserve=*/0);
1988 
1989   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(
1990       proxy, ProxyHost::GetMaxNumAclConnections()));
1991 
1992   for (uint16_t send = 1; send <= ProxyHost::GetMaxNumAclConnections();
1993        send++) {
1994     // Use current send count as the connection handle.
1995     uint16_t conn_handle = send;
1996     GattNotifyChannel channel =
1997         BuildGattNotifyChannel(proxy, {.handle = conn_handle});
1998     EXPECT_EQ(channel.Write(MultiBufFromArray(attribute_value)).status,
1999               PW_STATUS_OK);
2000     EXPECT_EQ(capture.sends_called, send);
2001   }
2002 }
2003 
TEST_F(MultiSendTest,AttemptToCreateOverMaxConnectionsFails)2004 TEST_F(MultiSendTest, AttemptToCreateOverMaxConnectionsFails) {
2005   constexpr uint16_t kSends = ProxyHost::GetMaxNumAclConnections() + 1;
2006 
2007   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2008       []([[maybe_unused]] H4PacketWithHci&& packet) {});
2009   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
2010       []([[maybe_unused]] H4PacketWithH4&& packet) {});
2011 
2012   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2013                               std::move(send_to_controller_fn),
2014                               /*le_acl_credits_to_reserve=*/kSends,
2015                               /*br_edr_acl_credits_to_reserve=*/0);
2016 
2017   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, kSends));
2018 
2019   std::vector<GattNotifyChannel> channels;
2020 
2021   for (uint16_t send = 1; send <= ProxyHost::GetMaxNumAclConnections();
2022        send++) {
2023     // Use current send count as the connection handle.
2024     uint16_t conn_handle = send;
2025     GattNotifyChannel channel =
2026         BuildGattNotifyChannel(proxy, {.handle = conn_handle});
2027     channels.push_back(std::move(channel));
2028   }
2029 
2030   // Last one should fail
2031   EXPECT_EQ(
2032       BuildGattNotifyChannelWithResult(proxy, {.handle = kSends}).status(),
2033       Status::Unavailable());
2034 }
2035 
2036 // ########## BasicL2capChannelTest
2037 
2038 class BasicL2capChannelTest : public ProxyHostTest {};
2039 
TEST_F(BasicL2capChannelTest,BasicWrite)2040 TEST_F(BasicL2capChannelTest, BasicWrite) {
2041   struct {
2042     int sends_called = 0;
2043     // First four bits 0x0 encode PB & BC flags
2044     uint16_t handle = 0x0ACB;
2045     // Length of L2CAP PDU
2046     uint16_t acl_data_total_length = 0x0007;
2047     // L2CAP header PDU length field
2048     uint16_t pdu_length = 0x0003;
2049     // Random CID
2050     uint16_t channel_id = 0x1234;
2051     // L2CAP information payload
2052     std::array<uint8_t, 3> payload = {0xAB, 0xCD, 0xEF};
2053 
2054     // Built from the preceding values in little endian order (except payload in
2055     // big endian).
2056     std::array<uint8_t, 11> expected_hci_packet = {
2057         0xCB, 0x0A, 0x07, 0x00, 0x03, 0x00, 0x34, 0x12, 0xAB, 0xCD, 0xEF};
2058   } capture;
2059 
2060   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2061       []([[maybe_unused]] H4PacketWithHci&& packet) {});
2062   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2063       [&capture](H4PacketWithH4&& packet) {
2064         ++capture.sends_called;
2065         EXPECT_EQ(packet.GetH4Type(), emboss::H4PacketType::ACL_DATA);
2066         EXPECT_EQ(packet.GetHciSpan().size(),
2067                   capture.expected_hci_packet.size());
2068         EXPECT_TRUE(std::equal(packet.GetHciSpan().begin(),
2069                                packet.GetHciSpan().end(),
2070                                capture.expected_hci_packet.begin(),
2071                                capture.expected_hci_packet.end()));
2072         PW_TEST_ASSERT_OK_AND_ASSIGN(
2073             auto acl,
2074             MakeEmbossView<emboss::AclDataFrameView>(packet.GetHciSpan()));
2075         EXPECT_EQ(acl.header().handle().Read(), capture.handle);
2076         EXPECT_EQ(acl.header().packet_boundary_flag().Read(),
2077                   emboss::AclDataPacketBoundaryFlag::FIRST_NON_FLUSHABLE);
2078         EXPECT_EQ(acl.header().broadcast_flag().Read(),
2079                   emboss::AclDataPacketBroadcastFlag::POINT_TO_POINT);
2080         EXPECT_EQ(acl.data_total_length().Read(),
2081                   capture.acl_data_total_length);
2082         emboss::BFrameView bframe = emboss::MakeBFrameView(
2083             acl.payload().BackingStorage().data(), acl.SizeInBytes());
2084         EXPECT_EQ(bframe.pdu_length().Read(), capture.pdu_length);
2085         EXPECT_EQ(bframe.channel_id().Read(), capture.channel_id);
2086         for (size_t i = 0; i < 3; ++i) {
2087           EXPECT_EQ(bframe.payload()[i].Read(), capture.payload[i]);
2088         }
2089       });
2090 
2091   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2092                               std::move(send_to_controller_fn),
2093                               /*le_acl_credits_to_reserve=*/1,
2094                               /*br_edr_acl_credits_to_reserve=*/0);
2095   // Allow proxy to reserve 1 LE credit.
2096   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
2097 
2098   BasicL2capChannel channel =
2099       BuildBasicL2capChannel(proxy,
2100                              {.handle = capture.handle,
2101                               .local_cid = 0x123,
2102                               .remote_cid = capture.channel_id,
2103                               .transport = AclTransportType::kLe});
2104 
2105   PW_TEST_EXPECT_OK(
2106       channel.Write(MultiBufFromSpan(pw::span(capture.payload))).status);
2107   EXPECT_EQ(capture.sends_called, 1);
2108 }
2109 
TEST_F(BasicL2capChannelTest,ErrorOnWriteTooLarge)2110 TEST_F(BasicL2capChannelTest, ErrorOnWriteTooLarge) {
2111   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2112       [](H4PacketWithHci&&) {});
2113   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2114       [](H4PacketWithH4&&) { FAIL(); });
2115 
2116   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2117                               std::move(send_to_controller_fn),
2118                               /*le_acl_credits_to_reserve=*/1,
2119                               /*br_edr_acl_credits_to_reserve=*/0);
2120   // Allow proxy to reserve 1 credit.
2121   PW_TEST_EXPECT_OK(SendReadBufferResponseFromController(proxy, 1));
2122 
2123   std::array<uint8_t,
2124              ProxyHost::GetMaxAclSendSize() -
2125                  emboss::AclDataFrameHeader::IntrinsicSizeInBytes() -
2126                  emboss::BasicL2capHeader::IntrinsicSizeInBytes() + 1>
2127       hci_arr;
2128 
2129   BasicL2capChannel channel =
2130       BuildBasicL2capChannel(proxy,
2131                              {.handle = 0x123,
2132                               .local_cid = 0x123,
2133                               .remote_cid = 0x123,
2134                               .transport = AclTransportType::kLe});
2135 
2136   EXPECT_EQ(channel.Write(MultiBufFromSpan(pw::span(hci_arr))).status,
2137             PW_STATUS_INVALID_ARGUMENT);
2138 }
2139 
TEST_F(BasicL2capChannelTest,CannotCreateChannelWithInvalidArgs)2140 TEST_F(BasicL2capChannelTest, CannotCreateChannelWithInvalidArgs) {
2141   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2142       [](H4PacketWithHci&&) {});
2143   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2144       [](H4PacketWithH4&&) {});
2145 
2146   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2147                               std::move(send_to_controller_fn),
2148                               /*le_acl_credits_to_reserve=*/0,
2149                               /*br_edr_acl_credits_to_reserve=*/0);
2150 
2151   // Connection handle too large by 1.
2152 
2153   Result<BasicL2capChannel> channel =
2154       BuildBasicL2capChannelWithResult(proxy,
2155                                        {.handle = 0x0FFF,
2156                                         .local_cid = 0x123,
2157                                         .remote_cid = 0x123,
2158                                         .transport = AclTransportType::kLe});
2159   EXPECT_EQ(channel.status(), Status::InvalidArgument());
2160 
2161   // Local CID invalid (0).
2162   channel =
2163       BuildBasicL2capChannelWithResult(proxy,
2164                                        BasicL2capParameters{
2165                                            .handle = 0x123,
2166                                            .local_cid = 0,
2167                                            .remote_cid = 0x123,
2168                                            .transport = AclTransportType::kLe,
2169                                        });
2170   EXPECT_EQ(channel.status(), Status::InvalidArgument());
2171 }
2172 
TEST_F(BasicL2capChannelTest,BasicRead)2173 TEST_F(BasicL2capChannelTest, BasicRead) {
2174   struct {
2175     int sends_called = 0;
2176     int to_host_called = 0;
2177     std::array<uint8_t, 3> expected_payload = {0xAB, 0xCD, 0xEF};
2178   } capture;
2179 
2180   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2181       [&capture](H4PacketWithHci&&) { ++capture.to_host_called; });
2182   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2183       [](H4PacketWithH4&&) {});
2184   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2185                               std::move(send_to_controller_fn),
2186                               /*le_acl_credits_to_reserve=*/0,
2187                               /*br_edr_acl_credits_to_reserve=*/0);
2188 
2189   uint16_t handle = 334;
2190   uint16_t local_cid = 443;
2191   BasicL2capChannel channel = BuildBasicL2capChannel(
2192       proxy,
2193       BasicL2capParameters{
2194           .handle = handle,
2195           .local_cid = local_cid,
2196           .remote_cid = 0x123,
2197           .transport = AclTransportType::kLe,
2198           .payload_from_controller_fn =
2199               [&capture](multibuf::MultiBuf&& buffer) {
2200                 ++capture.sends_called;
2201                 std::optional<pw::ByteSpan> payload = buffer.ContiguousSpan();
2202                 ConstByteSpan expected_bytes =
2203                     as_bytes(span(capture.expected_payload.data(),
2204                                   capture.expected_payload.size()));
2205                 EXPECT_TRUE(payload.has_value());
2206                 EXPECT_TRUE(std::equal(payload->begin(),
2207                                        payload->end(),
2208                                        expected_bytes.begin(),
2209                                        expected_bytes.end()));
2210                 return std::nullopt;
2211               },
2212       });
2213 
2214   std::array<uint8_t,
2215              emboss::AclDataFrameHeader::IntrinsicSizeInBytes() +
2216                  emboss::BasicL2capHeader::IntrinsicSizeInBytes() +
2217                  capture.expected_payload.size()>
2218       hci_arr;
2219   hci_arr.fill(0);
2220   H4PacketWithHci h4_packet{emboss::H4PacketType::ACL_DATA, hci_arr};
2221 
2222   Result<emboss::AclDataFrameWriter> acl =
2223       MakeEmbossWriter<emboss::AclDataFrameWriter>(hci_arr);
2224   acl->header().handle().Write(handle);
2225   acl->data_total_length().Write(
2226       emboss::BasicL2capHeader::IntrinsicSizeInBytes() +
2227       capture.expected_payload.size());
2228 
2229   emboss::BFrameWriter bframe = emboss::MakeBFrameView(
2230       acl->payload().BackingStorage().data(), acl->payload().SizeInBytes());
2231   bframe.pdu_length().Write(capture.expected_payload.size());
2232   bframe.channel_id().Write(local_cid);
2233   std::copy(capture.expected_payload.begin(),
2234             capture.expected_payload.end(),
2235             hci_arr.begin() +
2236                 emboss::AclDataFrameHeader::IntrinsicSizeInBytes() +
2237                 emboss::BasicL2capHeader::IntrinsicSizeInBytes());
2238 
2239   // Send ACL data packet destined for the CoC we registered.
2240   proxy.HandleH4HciFromController(std::move(h4_packet));
2241 
2242   EXPECT_EQ(capture.sends_called, 1);
2243   EXPECT_EQ(capture.to_host_called, 0);
2244 }
2245 
TEST_F(BasicL2capChannelTest,BasicForward)2246 TEST_F(BasicL2capChannelTest, BasicForward) {
2247   struct {
2248     int sends_called = 0;
2249     int to_host_called = 0;
2250     std::array<uint8_t, 3> expected_payload = {0xAB, 0xCD, 0xEF};
2251     std::array<uint8_t,
2252                emboss::AclDataFrameHeader::IntrinsicSizeInBytes() +
2253                    emboss::BasicL2capHeader::IntrinsicSizeInBytes() + 3>
2254         hci_arr{};
2255   } capture;
2256 
2257   H4PacketWithHci h4_packet{emboss::H4PacketType::ACL_DATA, capture.hci_arr};
2258 
2259   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2260       [&capture](H4PacketWithHci&& packet) {
2261         ++capture.to_host_called;
2262         EXPECT_TRUE(std::equal(packet.GetHciSpan().begin(),
2263                                packet.GetHciSpan().end(),
2264                                capture.hci_arr.begin(),
2265                                capture.hci_arr.end()));
2266       });
2267   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2268       [](H4PacketWithH4&&) {});
2269   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2270                               std::move(send_to_controller_fn),
2271                               /*le_acl_credits_to_reserve=*/0,
2272                               /*br_edr_acl_credits_to_reserve=*/0);
2273 
2274   uint16_t handle = 334;
2275   uint16_t local_cid = 443;
2276   BasicL2capChannel channel =
2277       BuildBasicL2capChannel(proxy,
2278                              BasicL2capParameters{
2279                                  .handle = handle,
2280                                  .local_cid = local_cid,
2281                                  .remote_cid = 0x123,
2282                                  .transport = AclTransportType::kLe,
2283                                  .payload_from_controller_fn =
2284                                      [&capture](multibuf::MultiBuf&& buffer) {
2285                                        ++capture.sends_called;
2286                                        // Forward to host.
2287                                        return std::move(buffer);
2288                                      },
2289                              });
2290 
2291   Result<emboss::AclDataFrameWriter> acl =
2292       MakeEmbossWriter<emboss::AclDataFrameWriter>(capture.hci_arr);
2293   acl->header().handle().Write(handle);
2294   acl->data_total_length().Write(
2295       emboss::BasicL2capHeader::IntrinsicSizeInBytes() +
2296       capture.expected_payload.size());
2297 
2298   emboss::BFrameWriter bframe = emboss::MakeBFrameView(
2299       acl->payload().BackingStorage().data(), acl->payload().SizeInBytes());
2300   bframe.pdu_length().Write(capture.expected_payload.size());
2301   bframe.channel_id().Write(local_cid);
2302   std::copy(capture.expected_payload.begin(),
2303             capture.expected_payload.end(),
2304             capture.hci_arr.begin() +
2305                 emboss::AclDataFrameHeader::IntrinsicSizeInBytes() +
2306                 emboss::BasicL2capHeader::IntrinsicSizeInBytes());
2307 
2308   // Send ACL data packet destined for the CoC we registered.
2309   proxy.HandleH4HciFromController(std::move(h4_packet));
2310 
2311   EXPECT_EQ(capture.sends_called, 1);
2312   EXPECT_EQ(capture.to_host_called, 1);
2313 }
2314 
TEST_F(BasicL2capChannelTest,ReadPacketToController)2315 TEST_F(BasicL2capChannelTest, ReadPacketToController) {
2316   struct {
2317     int sends_called = 0;
2318     int from_host_called = 0;
2319     std::array<uint8_t, 3> expected_payload = {0xAB, 0xCD, 0xEF};
2320     std::array<uint8_t,
2321                emboss::AclDataFrameHeader::IntrinsicSizeInBytes() +
2322                    emboss::BasicL2capHeader::IntrinsicSizeInBytes() + 3>
2323         hci_arr{};
2324   } capture;
2325 
2326   std::array<uint8_t, sizeof(emboss::H4PacketType) + capture.hci_arr.size()>
2327       h4_arr;
2328   h4_arr[0] = cpp23::to_underlying(emboss::H4PacketType::ACL_DATA);
2329   H4PacketWithH4 h4_packet{h4_arr};
2330 
2331   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2332       [](H4PacketWithHci&&) {});
2333   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2334       [&capture](H4PacketWithH4&& packet) {
2335         ++capture.from_host_called;
2336         EXPECT_TRUE(std::equal(packet.GetHciSpan().begin(),
2337                                packet.GetHciSpan().end(),
2338                                capture.hci_arr.begin(),
2339                                capture.hci_arr.end()));
2340       });
2341   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2342                               std::move(send_to_controller_fn),
2343                               /*le_acl_credits_to_reserve=*/0,
2344                               /*br_edr_acl_credits_to_reserve=*/0);
2345   uint16_t handle = 0x334;
2346   uint16_t local_cid = 0x443;
2347   uint16_t remote_cid = 0x123;
2348   BasicL2capChannel channel =
2349       BuildBasicL2capChannel(proxy,
2350                              BasicL2capParameters{
2351                                  .handle = handle,
2352                                  .local_cid = local_cid,
2353                                  .remote_cid = remote_cid,
2354                                  .transport = AclTransportType::kBrEdr,
2355                                  .payload_from_host_fn =
2356                                      [&capture](multibuf::MultiBuf&& buffer) {
2357                                        ++capture.sends_called;
2358                                        return std::move(buffer);
2359                                      },
2360                              });
2361 
2362   Result<emboss::AclDataFrameWriter> acl =
2363       MakeEmbossWriter<emboss::AclDataFrameWriter>(capture.hci_arr);
2364   acl->header().handle().Write(handle);
2365   acl->data_total_length().Write(
2366       emboss::BasicL2capHeader::IntrinsicSizeInBytes() +
2367       capture.expected_payload.size());
2368 
2369   emboss::BasicL2capHeaderWriter l2cap_header =
2370       emboss::MakeBasicL2capHeaderView(
2371           acl->payload().BackingStorage().data(),
2372           acl->payload().BackingStorage().SizeInBytes());
2373   l2cap_header.pdu_length().Write(capture.expected_payload.size());
2374   l2cap_header.channel_id().Write(remote_cid);
2375 
2376   std::copy(capture.expected_payload.begin(),
2377             capture.expected_payload.end(),
2378             capture.hci_arr.begin() +
2379                 emboss::AclDataFrameHeader::IntrinsicSizeInBytes() +
2380                 emboss::BasicL2capHeader::IntrinsicSizeInBytes());
2381 
2382   std::copy(capture.hci_arr.begin(), capture.hci_arr.end(), h4_arr.begin() + 1);
2383 
2384   proxy.HandleH4HciFromHost(std::move(h4_packet));
2385 
2386   EXPECT_EQ(capture.from_host_called, 1);
2387   EXPECT_EQ(capture.sends_called, 1);
2388 }
2389 
2390 // ########## L2capSignalingTest
2391 
2392 class L2capSignalingTest : public ProxyHostTest {};
2393 
TEST_F(L2capSignalingTest,FlowControlCreditIndDrainsQueue)2394 TEST_F(L2capSignalingTest, FlowControlCreditIndDrainsQueue) {
2395   size_t sends_called = 0;
2396 
2397   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2398       []([[maybe_unused]] H4PacketWithHci&& packet) {});
2399   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2400       [&sends_called]([[maybe_unused]] H4PacketWithH4&& packet) {
2401         ++sends_called;
2402       });
2403   ProxyHost proxy =
2404       ProxyHost(std::move(send_to_host_fn),
2405                 std::move(send_to_controller_fn),
2406                 /*le_acl_credits_to_reserve=*/L2capCoc::QueueCapacity(),
2407                 /*br_edr_acl_credits_to_reserve=*/0);
2408   PW_TEST_EXPECT_OK(
2409       SendLeReadBufferResponseFromController(proxy, L2capCoc::QueueCapacity()));
2410   EXPECT_EQ(proxy.GetNumFreeLeAclPackets(), L2capCoc::QueueCapacity());
2411 
2412   uint16_t handle = 123;
2413   uint16_t remote_cid = 456;
2414   L2capCoc channel = BuildCoc(
2415       proxy,
2416       CocParameters{
2417           .handle = handle, .remote_cid = remote_cid, .tx_credits = 0});
2418 
2419   for (size_t i = 0; i < L2capCoc::QueueCapacity(); ++i) {
2420     PW_TEST_EXPECT_OK(channel.Write(multibuf::MultiBuf{}).status);
2421   }
2422   EXPECT_EQ(channel.Write(multibuf::MultiBuf{}).status, Status::Unavailable());
2423   EXPECT_EQ(sends_called, 0u);
2424 
2425   constexpr size_t kL2capLength =
2426       emboss::BasicL2capHeader::IntrinsicSizeInBytes() +
2427       emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes();
2428   constexpr size_t kHciLength =
2429       emboss::AclDataFrame::MinSizeInBytes() + kL2capLength;
2430   std::array<uint8_t, kHciLength> hci_arr;
2431   hci_arr.fill(0);
2432   H4PacketWithHci flow_control_credit_ind{emboss::H4PacketType::ACL_DATA,
2433                                           pw::span(hci_arr.data(), kHciLength)};
2434 
2435   Result<emboss::AclDataFrameWriter> acl =
2436       MakeEmbossWriter<emboss::AclDataFrameWriter>(hci_arr);
2437   acl->header().handle().Write(handle);
2438   acl->data_total_length().Write(kL2capLength);
2439 
2440   emboss::CFrameWriter l2cap = emboss::MakeCFrameView(
2441       acl->payload().BackingStorage().data(), kL2capLength);
2442   l2cap.pdu_length().Write(
2443       emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes());
2444   // 0x0005 = LE-U fixed signaling channel ID.
2445   l2cap.channel_id().Write(0x0005);
2446 
2447   emboss::L2capFlowControlCreditIndWriter ind =
2448       emboss::MakeL2capFlowControlCreditIndView(
2449           l2cap.payload().BackingStorage().data(),
2450           emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes());
2451   ind.command_header().code().Write(
2452       emboss::L2capSignalingPacketCode::FLOW_CONTROL_CREDIT_IND);
2453   ind.command_header().data_length().Write(
2454       emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes() -
2455       emboss::L2capSignalingCommandHeader::IntrinsicSizeInBytes());
2456   ind.cid().Write(remote_cid);
2457   ind.credits().Write(L2capCoc::QueueCapacity());
2458 
2459   proxy.HandleH4HciFromController(std::move(flow_control_credit_ind));
2460 
2461   EXPECT_EQ(sends_called, L2capCoc::QueueCapacity());
2462 }
2463 
TEST_F(L2capSignalingTest,ChannelClosedWithErrorIfCreditsExceeded)2464 TEST_F(L2capSignalingTest, ChannelClosedWithErrorIfCreditsExceeded) {
2465   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2466       []([[maybe_unused]] H4PacketWithHci&& packet) {});
2467   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2468       []([[maybe_unused]] H4PacketWithH4&& packet) {});
2469 
2470   ProxyHost proxy =
2471       ProxyHost(std::move(send_to_host_fn),
2472                 std::move(send_to_controller_fn),
2473                 /*le_acl_credits_to_reserve=*/L2capCoc::QueueCapacity(),
2474                 /*br_edr_acl_credits_to_reserve=*/0);
2475 
2476   uint16_t handle = 123;
2477   uint16_t remote_cid = 456;
2478   int events_received = 0;
2479   L2capCoc channel = BuildCoc(
2480       proxy,
2481       CocParameters{
2482           .handle = handle,
2483           .remote_cid = remote_cid,
2484           // Initialize with max credit count.
2485           .tx_credits =
2486               emboss::L2capLeCreditBasedConnectionReq::max_credit_value(),
2487           .event_fn = [&events_received](L2capChannelEvent event) {
2488             EXPECT_EQ(event, L2capChannelEvent::kRxInvalid);
2489             ++events_received;
2490           }});
2491 
2492   constexpr size_t kL2capLength =
2493       emboss::BasicL2capHeader::IntrinsicSizeInBytes() +
2494       emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes();
2495   constexpr size_t kHciLength =
2496       emboss::AclDataFrame::MinSizeInBytes() + kL2capLength;
2497   std::array<uint8_t, kHciLength> hci_arr;
2498   hci_arr.fill(0);
2499   H4PacketWithHci flow_control_credit_ind{emboss::H4PacketType::ACL_DATA,
2500                                           pw::span(hci_arr.data(), kHciLength)};
2501 
2502   Result<emboss::AclDataFrameWriter> acl =
2503       MakeEmbossWriter<emboss::AclDataFrameWriter>(hci_arr);
2504   acl->header().handle().Write(handle);
2505   acl->data_total_length().Write(kL2capLength);
2506 
2507   emboss::CFrameWriter l2cap =
2508       emboss::MakeCFrameView(acl->payload().BackingStorage().data(),
2509                              emboss::BasicL2capHeader::IntrinsicSizeInBytes());
2510   l2cap.pdu_length().Write(
2511       emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes());
2512   // 0x0005 = LE-U fixed signaling channel ID.
2513   l2cap.channel_id().Write(0x0005);
2514 
2515   emboss::L2capFlowControlCreditIndWriter ind =
2516       emboss::MakeL2capFlowControlCreditIndView(
2517           l2cap.payload().BackingStorage().data(),
2518           emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes());
2519   ind.command_header().code().Write(
2520       emboss::L2capSignalingPacketCode::FLOW_CONTROL_CREDIT_IND);
2521   ind.command_header().data_length().Write(
2522       emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes() -
2523       emboss::L2capSignalingCommandHeader::IntrinsicSizeInBytes());
2524   ind.cid().Write(remote_cid);
2525   // Exceed max credit count by 1.
2526   ind.credits().Write(1);
2527 
2528   proxy.HandleH4HciFromController(std::move(flow_control_credit_ind));
2529 
2530   EXPECT_EQ(events_received, 1);
2531 }
2532 
TEST_F(L2capSignalingTest,SignalsArePassedOnToHost)2533 TEST_F(L2capSignalingTest, SignalsArePassedOnToHost) {
2534   int forwards_to_host = 0;
2535   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2536       [&forwards_to_host](H4PacketWithHci&&) { ++forwards_to_host; });
2537   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2538       [](H4PacketWithH4&&) {});
2539 
2540   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2541                               std::move(send_to_controller_fn),
2542                               /*le_acl_credits_to_reserve=*/0,
2543                               /*br_edr_acl_credits_to_reserve=*/0);
2544 
2545   EXPECT_EQ(forwards_to_host, 0);
2546 
2547   PW_TEST_EXPECT_OK(SendL2capConnectionReq(proxy, 44, 55, 56));
2548   EXPECT_EQ(forwards_to_host, 1);
2549 }
2550 
TEST_F(L2capSignalingTest,SignalsArePassedOnToHostAfterAclDisconnect)2551 TEST_F(L2capSignalingTest, SignalsArePassedOnToHostAfterAclDisconnect) {
2552   uint16_t kConnHandle = 0x33;
2553   int sends_to_host = 0;
2554   int sends_to_controller = 0;
2555   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2556       [&sends_to_host](H4PacketWithHci&&) { ++sends_to_host; });
2557   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2558       [&sends_to_controller](H4PacketWithH4&&) { ++sends_to_controller; });
2559 
2560   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2561                               std::move(send_to_controller_fn),
2562                               /*le_acl_credits_to_reserve=*/1,
2563                               /*br_edr_acl_credits_to_reserve=*/0);
2564   // Allow proxy to reserve 1 credit.
2565   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
2566   EXPECT_EQ(sends_to_host, 1);
2567 
2568   // Send GATT Notify which should create ACL connection for kConnHandle.
2569   std::array<uint8_t, 1> attribute_value = {0};
2570   {
2571     GattNotifyChannel channel =
2572         BuildGattNotifyChannel(proxy, {.handle = kConnHandle});
2573     PW_TEST_EXPECT_OK(channel.Write(MultiBufFromArray(attribute_value)).status);
2574   }
2575   EXPECT_EQ(sends_to_controller, 1);
2576 
2577   // Disconnect that connection.
2578   PW_TEST_EXPECT_OK(
2579       SendDisconnectionCompleteEvent(proxy, /*handle=*/kConnHandle));
2580   EXPECT_EQ(sends_to_host, 2);
2581 
2582   // Send signal again using the same connection. Signal should be passed on
2583   // to host.
2584   PW_TEST_EXPECT_OK(
2585       SendL2capConnectionReq(proxy, /*handle=*/kConnHandle, 55, 56));
2586   EXPECT_EQ(sends_to_host, 3);
2587 
2588   // Trigger credit send for L2capCoc to verify new signalling channel
2589   // object is present and working.
2590   {
2591     L2capCoc channel = BuildCoc(proxy, CocParameters{.handle = kConnHandle});
2592     PW_TEST_EXPECT_OK(channel.SendAdditionalRxCredits(7));
2593   }
2594   EXPECT_EQ(sends_to_controller, 2);
2595 }
2596 
TEST_F(L2capSignalingTest,CreditIndAddressedToNonManagedChannelForwardedToHost)2597 TEST_F(L2capSignalingTest,
2598        CreditIndAddressedToNonManagedChannelForwardedToHost) {
2599   int forwards_to_host = 0;
2600   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2601       [&forwards_to_host](H4PacketWithHci&&) { ++forwards_to_host; });
2602   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2603       [](H4PacketWithH4&&) {});
2604 
2605   ProxyHost proxy =
2606       ProxyHost(std::move(send_to_host_fn),
2607                 std::move(send_to_controller_fn),
2608                 /*le_acl_credits_to_reserve=*/L2capCoc::QueueCapacity(),
2609                 /*br_edr_acl_credits_to_reserve=*/0);
2610 
2611   uint16_t handle = 123;
2612   uint16_t remote_cid = 456;
2613   L2capCoc channel = BuildCoc(
2614       proxy, CocParameters{.handle = handle, .remote_cid = remote_cid});
2615 
2616   constexpr size_t kL2capLength =
2617       emboss::BasicL2capHeader::IntrinsicSizeInBytes() +
2618       emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes();
2619   constexpr size_t kHciLength =
2620       emboss::AclDataFrame::MinSizeInBytes() + kL2capLength;
2621   std::array<uint8_t, kHciLength> hci_arr;
2622   hci_arr.fill(0);
2623   H4PacketWithHci flow_control_credit_ind{emboss::H4PacketType::ACL_DATA,
2624                                           pw::span(hci_arr.data(), kHciLength)};
2625 
2626   Result<emboss::AclDataFrameWriter> acl =
2627       MakeEmbossWriter<emboss::AclDataFrameWriter>(hci_arr);
2628   acl->header().handle().Write(handle);
2629   acl->data_total_length().Write(kL2capLength);
2630 
2631   emboss::CFrameWriter l2cap =
2632       emboss::MakeCFrameView(acl->payload().BackingStorage().data(),
2633                              emboss::BasicL2capHeader::IntrinsicSizeInBytes());
2634   l2cap.pdu_length().Write(
2635       emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes());
2636   // 0x0005 = LE-U fixed signaling channel ID.
2637   l2cap.channel_id().Write(0x0005);
2638 
2639   emboss::L2capFlowControlCreditIndWriter ind =
2640       emboss::MakeL2capFlowControlCreditIndView(
2641           l2cap.payload().BackingStorage().data(),
2642           emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes());
2643   ind.command_header().code().Write(
2644       emboss::L2capSignalingPacketCode::FLOW_CONTROL_CREDIT_IND);
2645   ind.command_header().data_length().Write(
2646       emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes() -
2647       emboss::L2capSignalingCommandHeader::IntrinsicSizeInBytes());
2648   // Address packet to different CID on same connection.
2649   ind.cid().Write(remote_cid + 1);
2650 
2651   proxy.HandleH4HciFromController(std::move(flow_control_credit_ind));
2652 
2653   EXPECT_EQ(forwards_to_host, 1);
2654 }
2655 
TEST_F(L2capSignalingTest,RxAdditionalCreditsSent)2656 TEST_F(L2capSignalingTest, RxAdditionalCreditsSent) {
2657   struct {
2658     uint16_t handle = 123;
2659     uint16_t local_cid = 456;
2660     uint16_t credits = 3;
2661     int sends_called = 0;
2662   } capture;
2663 
2664   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2665       [](H4PacketWithHci&&) {});
2666   pw::Function<void(H4PacketWithH4 && packet)>&& send_to_controller_fn(
2667       [&capture](H4PacketWithH4&& packet) {
2668         ++capture.sends_called;
2669         PW_TEST_ASSERT_OK_AND_ASSIGN(
2670             auto acl,
2671             MakeEmbossView<emboss::AclDataFrameView>(packet.GetHciSpan()));
2672         EXPECT_EQ(acl.header().handle().Read(), capture.handle);
2673         EXPECT_EQ(
2674             acl.data_total_length().Read(),
2675             emboss::BasicL2capHeader::IntrinsicSizeInBytes() +
2676                 emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes());
2677         emboss::CFrameView cframe = emboss::MakeCFrameView(
2678             acl.payload().BackingStorage().data(), acl.payload().SizeInBytes());
2679         EXPECT_EQ(cframe.pdu_length().Read(),
2680                   emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes());
2681         // 0x0005 = LE-U fixed signaling channel ID.
2682         EXPECT_EQ(cframe.channel_id().Read(), 0x0005);
2683         emboss::L2capFlowControlCreditIndView ind =
2684             emboss::MakeL2capFlowControlCreditIndView(
2685                 cframe.payload().BackingStorage().data(),
2686                 cframe.payload().SizeInBytes());
2687         EXPECT_EQ(ind.command_header().code().Read(),
2688                   emboss::L2capSignalingPacketCode::FLOW_CONTROL_CREDIT_IND);
2689         // TODO: https://pwbug.dev/382553099 - Test to ensure we are properly
2690         // incrementing Identifier when sending multiple signaling packets.
2691         EXPECT_EQ(ind.command_header().identifier().Read(), 1);
2692         EXPECT_EQ(
2693             ind.command_header().data_length().Read(),
2694             emboss::L2capFlowControlCreditInd::IntrinsicSizeInBytes() -
2695                 emboss::L2capSignalingCommandHeader::IntrinsicSizeInBytes());
2696         EXPECT_EQ(ind.cid().Read(), capture.local_cid);
2697         EXPECT_EQ(ind.credits().Read(), capture.credits);
2698       });
2699 
2700   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2701                               std::move(send_to_controller_fn),
2702                               /*le_acl_credits_to_reserve=*/1,
2703                               /*br_edr_acl_credits_to_reserve=*/0);
2704   // Allow proxy to reserve 1 LE credit.
2705   PW_TEST_EXPECT_OK(SendLeReadBufferResponseFromController(proxy, 1));
2706 
2707   // Build channel so ACL connection is registered.
2708   L2capCoc channel = BuildCoc(
2709       proxy,
2710       CocParameters{.handle = capture.handle, .local_cid = capture.local_cid});
2711 
2712   PW_TEST_EXPECT_OK(channel.SendAdditionalRxCredits(capture.credits));
2713 
2714   EXPECT_EQ(capture.sends_called, 1);
2715 }
2716 
2717 // ########## AcluSignalingChannelTest
2718 
2719 class AcluSignalingChannelTest : public ProxyHostTest {};
2720 
TEST_F(AcluSignalingChannelTest,HandlesMultipleCommands)2721 TEST_F(AcluSignalingChannelTest, HandlesMultipleCommands) {
2722   std::optional<H4PacketWithHci> host_packet;
2723   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2724       [&host_packet](H4PacketWithHci&& packet) {
2725         host_packet = std::move(packet);
2726       });
2727   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
2728       []([[maybe_unused]] H4PacketWithH4&& packet) {});
2729 
2730   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2731                               std::move(send_to_controller_fn),
2732                               /*le_acl_credits_to_reserve=*/1,
2733                               /*br_edr_acl_credits_to_reserve=*/0);
2734 
2735   constexpr uint16_t kHandle = 123;
2736 
2737   // Test that the proxy can parse a CFrame containing multiple commands and
2738   // pass it through. We pack 3 CONNECTION_REQ commands into one CFrame.
2739   constexpr size_t kNumCommands = 3;
2740   constexpr size_t kCmdLen = emboss::L2capConnectionReq::IntrinsicSizeInBytes();
2741   constexpr size_t kL2capLength =
2742       emboss::BasicL2capHeader::IntrinsicSizeInBytes() + kCmdLen * kNumCommands;
2743   constexpr size_t kHciLength =
2744       emboss::AclDataFrame::MinSizeInBytes() + kL2capLength;
2745   std::array<uint8_t, kHciLength> hci_arr{};
2746   H4PacketWithHci l2cap_cframe_packet{emboss::H4PacketType::ACL_DATA,
2747                                       pw::span(hci_arr.data(), kHciLength)};
2748 
2749   // ACL header
2750   PW_TEST_ASSERT_OK_AND_ASSIGN(
2751       auto acl, MakeEmbossWriter<emboss::AclDataFrameWriter>(hci_arr));
2752   acl.header().handle().Write(kHandle);
2753   acl.data_total_length().Write(kL2capLength);
2754   EXPECT_EQ(kL2capLength, acl.payload().BackingStorage().SizeInBytes());
2755 
2756   // L2CAP header
2757   auto l2cap =
2758       emboss::MakeCFrameView(acl.payload().BackingStorage().data(),
2759                              acl.payload().BackingStorage().SizeInBytes());
2760   l2cap.pdu_length().Write(kNumCommands * kCmdLen);
2761   l2cap.channel_id().Write(
2762       cpp23::to_underlying(emboss::L2capFixedCid::ACL_U_SIGNALING));
2763   EXPECT_TRUE(l2cap.Ok());
2764 
2765   auto command_buffer =
2766       pw::span(l2cap.payload().BackingStorage().data(),
2767                l2cap.payload().BackingStorage().SizeInBytes());
2768   EXPECT_EQ(l2cap.payload().BackingStorage().SizeInBytes(),
2769             kCmdLen * kNumCommands);
2770 
2771   do {
2772     // CONNECTION_REQ
2773     auto cmd_writer = emboss::MakeL2capConnectionReqView(command_buffer.data(),
2774                                                          command_buffer.size());
2775     cmd_writer.command_header().code().Write(
2776         emboss::L2capSignalingPacketCode::CONNECTION_REQ);
2777     // Note data_length doesn't include command header.
2778     cmd_writer.command_header().data_length().Write(
2779         kCmdLen - emboss::L2capSignalingCommandHeader::IntrinsicSizeInBytes());
2780     cmd_writer.psm().Write(1);
2781     cmd_writer.source_cid().Write(1);
2782     EXPECT_TRUE(cmd_writer.Ok());
2783     EXPECT_EQ(cmd_writer.SizeInBytes(), kCmdLen);
2784     command_buffer = command_buffer.subspan(cmd_writer.SizeInBytes());
2785   } while (!command_buffer.empty());
2786 
2787   proxy.HandleH4HciFromController(std::move(l2cap_cframe_packet));
2788   // We should get back what we sent, since the proxy doesn't consume
2789   // CONNECTION_REQ commands. It would be nice to also verify the individual
2790   // commands were parsed out but hooks don't exist for that at the time of
2791   // writing.
2792   EXPECT_TRUE(host_packet.has_value());
2793   EXPECT_EQ(host_packet->GetHciSpan().size(), kHciLength);
2794 }
2795 
TEST_F(AcluSignalingChannelTest,InvalidPacketForwarded)2796 TEST_F(AcluSignalingChannelTest, InvalidPacketForwarded) {
2797   std::optional<H4PacketWithHci> host_packet;
2798   pw::Function<void(H4PacketWithHci && packet)>&& send_to_host_fn(
2799       [&host_packet](H4PacketWithHci&& packet) {
2800         host_packet = std::move(packet);
2801       });
2802   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
2803       []([[maybe_unused]] H4PacketWithH4&& packet) {});
2804 
2805   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2806                               std::move(send_to_controller_fn),
2807                               /*le_acl_credits_to_reserve=*/1,
2808                               /*br_edr_acl_credits_to_reserve=*/0);
2809 
2810   constexpr uint16_t kHandle = 123;
2811 
2812   // Test that the proxy forwards on invalid L2cap B-frames destined for
2813   // signaling channel.
2814 
2815   constexpr size_t kL2capLength =
2816       emboss::BasicL2capHeader::IntrinsicSizeInBytes();
2817   constexpr size_t kHciLength =
2818       emboss::AclDataFrame::MinSizeInBytes() + kL2capLength;
2819   std::array<uint8_t, kHciLength> hci_arr{};
2820   H4PacketWithHci l2cap_cframe_packet{emboss::H4PacketType::ACL_DATA,
2821                                       pw::span(hci_arr.data(), kHciLength)};
2822 
2823   // ACL header
2824   PW_TEST_ASSERT_OK_AND_ASSIGN(
2825       auto acl, MakeEmbossWriter<emboss::AclDataFrameWriter>(hci_arr));
2826   acl.header().handle().Write(kHandle);
2827   acl.data_total_length().Write(kL2capLength);
2828   EXPECT_EQ(kL2capLength, acl.payload().BackingStorage().SizeInBytes());
2829 
2830   // L2CAP header
2831   auto l2cap =
2832       emboss::MakeCFrameView(acl.payload().BackingStorage().data(),
2833                              acl.payload().BackingStorage().SizeInBytes());
2834   // Invalid length, since we aren't encoding a payload.
2835   l2cap.pdu_length().Write(1);
2836   l2cap.channel_id().Write(
2837       cpp23::to_underlying(emboss::L2capFixedCid::ACL_U_SIGNALING));
2838   EXPECT_FALSE(l2cap.Ok());
2839 
2840   proxy.HandleH4HciFromController(std::move(l2cap_cframe_packet));
2841   // We should get back what we sent.
2842   EXPECT_TRUE(host_packet.has_value());
2843   EXPECT_EQ(host_packet->GetHciSpan().size(), kHciLength);
2844 }
2845 
2846 // ########## ProxyHostConnectionEventTest
2847 
2848 class ProxyHostConnectionEventTest : public ProxyHostTest {};
2849 
TEST_F(ProxyHostConnectionEventTest,ConnectionCompletePassthroughOk)2850 TEST_F(ProxyHostConnectionEventTest, ConnectionCompletePassthroughOk) {
2851   size_t host_called = 0;
2852   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
2853       []([[maybe_unused]] H4PacketWithH4&& packet) {});
2854 
2855   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
2856       [&host_called]([[maybe_unused]] H4PacketWithHci&& packet) {
2857         ++host_called;
2858       });
2859 
2860   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2861                               std::move(send_to_controller_fn),
2862                               /*le_acl_credits_to_reserve=*/0,
2863                               /*br_edr_acl_credits_to_reserve=*/0);
2864 
2865   PW_TEST_EXPECT_OK(
2866       SendConnectionCompleteEvent(proxy, 1, emboss::StatusCode::SUCCESS));
2867   EXPECT_EQ(host_called, 1U);
2868 
2869   PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(proxy, 1));
2870   EXPECT_EQ(host_called, 2U);
2871 }
2872 
TEST_F(ProxyHostConnectionEventTest,ConnectionCompleteWithErrorStatusPassthroughOk)2873 TEST_F(ProxyHostConnectionEventTest,
2874        ConnectionCompleteWithErrorStatusPassthroughOk) {
2875   size_t host_called = 0;
2876   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
2877       []([[maybe_unused]] H4PacketWithH4&& packet) {});
2878 
2879   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
2880       [&host_called]([[maybe_unused]] H4PacketWithHci&& packet) {
2881         ++host_called;
2882       });
2883 
2884   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2885                               std::move(send_to_controller_fn),
2886                               /*le_acl_credits_to_reserve=*/0,
2887                               /*br_edr_acl_credits_to_reserve=*/0);
2888 
2889   PW_TEST_EXPECT_OK(SendConnectionCompleteEvent(
2890       proxy, 1, emboss::StatusCode::CONNECTION_FAILED_TO_BE_ESTABLISHED));
2891   EXPECT_EQ(host_called, 1U);
2892 }
2893 
TEST_F(ProxyHostConnectionEventTest,LeConnectionCompletePassthroughOk)2894 TEST_F(ProxyHostConnectionEventTest, LeConnectionCompletePassthroughOk) {
2895   size_t host_called = 0;
2896   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
2897       []([[maybe_unused]] H4PacketWithH4&& packet) {});
2898 
2899   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
2900       [&host_called]([[maybe_unused]] H4PacketWithHci&& packet) {
2901         ++host_called;
2902       });
2903 
2904   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2905                               std::move(send_to_controller_fn),
2906                               /*le_acl_credits_to_reserve=*/0,
2907                               /*br_edr_acl_credits_to_reserve=*/0);
2908 
2909   PW_TEST_EXPECT_OK(
2910       SendLeConnectionCompleteEvent(proxy, 1, emboss::StatusCode::SUCCESS));
2911   EXPECT_EQ(host_called, 1U);
2912 }
2913 
2914 class L2capStatusTrackerTest : public ProxyHostTest,
2915                                public L2capStatusDelegate {
2916  public:
2917   static constexpr uint16_t kPsm = 1;
2918 
ShouldTrackPsm(uint16_t psm)2919   bool ShouldTrackPsm(uint16_t psm) override { return psm == kPsm; }
HandleConnectionComplete(const L2capChannelConnectionInfo & i)2920   void HandleConnectionComplete(const L2capChannelConnectionInfo& i) override {
2921     EXPECT_FALSE(info.has_value());
2922     PW_CHECK(proxy_ptr);
2923     info.emplace(i);
2924     // Test we can create channel directly in callback.
2925     l2cap_channel =
2926         BuildBasicL2capChannel(*proxy_ptr,
2927                                {.handle = i.connection_handle,
2928                                 .local_cid = i.local_cid,
2929                                 .remote_cid = i.remote_cid,
2930                                 .transport = AclTransportType::kBrEdr});
2931   }
HandleDisconnectionComplete(const L2capChannelConnectionInfo & i)2932   void HandleDisconnectionComplete(
2933       const L2capChannelConnectionInfo& i) override {
2934     ASSERT_TRUE(info.has_value());
2935     EXPECT_EQ(info->direction, i.direction);
2936     EXPECT_EQ(info->connection_handle, i.connection_handle);
2937     EXPECT_EQ(info->remote_cid, i.remote_cid);
2938     EXPECT_EQ(info->local_cid, i.local_cid);
2939     info.reset();
2940   }
2941 
2942   ProxyHost* proxy_ptr = nullptr;
2943   std::optional<L2capChannelConnectionInfo> info;
2944   std::optional<BasicL2capChannel> l2cap_channel;
2945 };
2946 
TEST_F(L2capStatusTrackerTest,L2capEventsCalled)2947 TEST_F(L2capStatusTrackerTest, L2capEventsCalled) {
2948   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
2949       []([[maybe_unused]] H4PacketWithH4&& packet) {});
2950 
2951   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
2952       []([[maybe_unused]] H4PacketWithHci&& packet) {});
2953 
2954   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
2955                               std::move(send_to_controller_fn),
2956                               /*le_acl_credits_to_reserve=*/0,
2957                               /*br_edr_acl_credits_to_reserve=*/0);
2958   proxy_ptr = &proxy;
2959 
2960   constexpr uint16_t kSourceCid = 30;
2961   constexpr uint16_t kDestinationCid = 31;
2962   constexpr uint16_t kHandle = 123;
2963 
2964   proxy.RegisterL2capStatusDelegate(*this);
2965 
2966   PW_TEST_EXPECT_OK(
2967       SendConnectionCompleteEvent(proxy, kHandle, emboss::StatusCode::SUCCESS));
2968 
2969   // First send CONNECTION_REQ to setup partial connection
2970   PW_TEST_EXPECT_OK(SendL2capConnectionReq(proxy, kHandle, kSourceCid, kPsm));
2971   EXPECT_FALSE(info.has_value());
2972 
2973   // Send non-successful connection response.
2974   PW_TEST_EXPECT_OK(SendL2capConnectionRsp(
2975       proxy,
2976       kHandle,
2977       kSourceCid,
2978       kDestinationCid,
2979       emboss::L2capConnectionRspResultCode::INVALID_SOURCE_CID));
2980   EXPECT_FALSE(info.has_value());
2981 
2982   // Send successful connection response, but expect that it will not have
2983   // called listener since the connection was closed with error already.
2984   PW_TEST_EXPECT_OK(
2985       SendL2capConnectionRsp(proxy,
2986                              kHandle,
2987                              kSourceCid,
2988                              kDestinationCid,
2989                              emboss::L2capConnectionRspResultCode::SUCCESSFUL));
2990   EXPECT_FALSE(info.has_value());
2991 
2992   // Send new connection req
2993   PW_TEST_EXPECT_OK(SendL2capConnectionReq(proxy, kHandle, kSourceCid, kPsm));
2994   EXPECT_FALSE(info.has_value());
2995 
2996   // Send rsp with PENDING set.
2997   PW_TEST_EXPECT_OK(
2998       SendL2capConnectionRsp(proxy,
2999                              kHandle,
3000                              kSourceCid,
3001                              kDestinationCid,
3002                              emboss::L2capConnectionRspResultCode::PENDING));
3003   EXPECT_FALSE(info.has_value());
3004 
3005   // Send success rsp
3006   PW_TEST_EXPECT_OK(
3007       SendL2capConnectionRsp(proxy,
3008                              kHandle,
3009                              kSourceCid,
3010                              kDestinationCid,
3011                              emboss::L2capConnectionRspResultCode::SUCCESSFUL));
3012   EXPECT_TRUE(info.has_value());
3013   EXPECT_EQ(info->local_cid, kDestinationCid);
3014 
3015   // Send disconnect
3016   PW_TEST_EXPECT_OK(SendL2capDisconnectRsp(
3017       proxy, AclTransportType::kBrEdr, kHandle, kSourceCid, kDestinationCid));
3018   EXPECT_FALSE(info.has_value());
3019 
3020   proxy.UnregisterL2capStatusDelegate(*this);
3021 
3022   // Send successful connection sequence with no listeners.
3023   PW_TEST_EXPECT_OK(SendL2capConnectionReq(proxy, kHandle, kSourceCid, kPsm));
3024   PW_TEST_EXPECT_OK(
3025       SendL2capConnectionRsp(proxy,
3026                              kHandle,
3027                              kSourceCid,
3028                              kDestinationCid,
3029                              emboss::L2capConnectionRspResultCode::SUCCESSFUL));
3030   EXPECT_FALSE(info.has_value());
3031 }
3032 
TEST_F(ProxyHostConnectionEventTest,HciDisconnectionAlertsListeners)3033 TEST_F(ProxyHostConnectionEventTest, HciDisconnectionAlertsListeners) {
3034   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
3035       [](H4PacketWithH4&&) {});
3036   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
3037       [](H4PacketWithHci&&) {});
3038   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
3039                               std::move(send_to_controller_fn),
3040                               /*le_acl_credits_to_reserve=*/0,
3041                               /*br_edr_acl_credits_to_reserve=*/0);
3042 
3043   constexpr uint16_t kPsm = 1;
3044 
3045   class TestStatusDelegate final : public L2capStatusDelegate {
3046    public:
3047     bool ShouldTrackPsm(uint16_t psm) override { return psm == kPsm; }
3048     void HandleConnectionComplete(const L2capChannelConnectionInfo&) override {
3049       ++connections_received;
3050     }
3051     void HandleDisconnectionComplete(
3052         const L2capChannelConnectionInfo&) override {
3053       ++disconnections_received;
3054     }
3055 
3056     int connections_received = 0;
3057     int disconnections_received = 0;
3058   };
3059 
3060   TestStatusDelegate test_delegate;
3061   proxy.RegisterL2capStatusDelegate(test_delegate);
3062 
3063   constexpr uint16_t Handle1 = 0x123, Handle2 = 0x124;
3064   PW_TEST_EXPECT_OK(
3065       SendConnectionCompleteEvent(proxy, Handle1, emboss::StatusCode::SUCCESS));
3066   PW_TEST_EXPECT_OK(
3067       SendConnectionCompleteEvent(proxy, Handle2, emboss::StatusCode::SUCCESS));
3068 
3069   // Establish three connected_channels:
3070   // handle = 0x123, PSM = 1 | handle = 0x124, PSM = 1 | handle = 0x123, PSM =
3071   // 1
3072   constexpr uint16_t kStartSourceCid = 0x111;
3073   constexpr uint16_t kStartDestinationCid = 0x211;
3074   for (size_t i = 0; i < 3; ++i) {
3075     PW_TEST_EXPECT_OK(SendL2capConnectionReq(
3076         proxy, i == 1 ? Handle2 : Handle1, kStartSourceCid + i, kPsm));
3077     PW_TEST_EXPECT_OK(SendL2capConnectionRsp(
3078         proxy,
3079         i == 1 ? Handle2 : Handle1,
3080         kStartSourceCid + i,
3081         kStartDestinationCid + i,
3082         emboss::L2capConnectionRspResultCode::SUCCESSFUL));
3083   }
3084 
3085   EXPECT_EQ(test_delegate.connections_received, 3);
3086   EXPECT_EQ(test_delegate.disconnections_received, 0);
3087 
3088   // Disconnect handle1, which should disconnect first and third channel.
3089   PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(proxy, Handle1));
3090   EXPECT_EQ(test_delegate.disconnections_received, 2);
3091 
3092   // Confirm remaining channel can still be disconnected properly.
3093   PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(proxy, Handle2));
3094   EXPECT_EQ(test_delegate.disconnections_received, 3);
3095 
3096   proxy.UnregisterL2capStatusDelegate(test_delegate);
3097 }
3098 
TEST_F(ProxyHostConnectionEventTest,HciDisconnectionFromControllerClosesChannels)3099 TEST_F(ProxyHostConnectionEventTest,
3100        HciDisconnectionFromControllerClosesChannels) {
3101   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
3102       [](H4PacketWithH4&&) {});
3103   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
3104       [](H4PacketWithHci&&) {});
3105   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
3106                               std::move(send_to_controller_fn),
3107                               /*le_acl_credits_to_reserve=*/0,
3108                               /*br_edr_acl_credits_to_reserve=*/0);
3109 
3110   constexpr uint16_t kHandle = 0x123;
3111   constexpr uint16_t kStartingCid = 0x111;
3112   int events_received = 0;
3113   auto event_fn = [&events_received](L2capChannelEvent event) {
3114     ++events_received;
3115     EXPECT_EQ(event, L2capChannelEvent::kChannelClosedByOther);
3116   };
3117   BasicL2capChannel chan1 = BuildBasicL2capChannel(proxy,
3118                                                    {.handle = kHandle,
3119                                                     .local_cid = kStartingCid,
3120                                                     .remote_cid = kStartingCid,
3121                                                     .event_fn = event_fn});
3122   // chan2 is on a different connection so should not be closed
3123   BasicL2capChannel chan2 =
3124       BuildBasicL2capChannel(proxy,
3125                              {.handle = kHandle + 1,
3126                               .local_cid = kStartingCid + 1,
3127                               .remote_cid = kStartingCid + 1,
3128                               .event_fn = event_fn});
3129   BasicL2capChannel chan3 =
3130       BuildBasicL2capChannel(proxy,
3131                              {.handle = kHandle,
3132                               .local_cid = kStartingCid + 2,
3133                               .remote_cid = kStartingCid + 2,
3134                               .event_fn = event_fn});
3135 
3136   EXPECT_EQ(chan1.state(), L2capChannel::State::kRunning);
3137   EXPECT_EQ(chan2.state(), L2capChannel::State::kRunning);
3138   EXPECT_EQ(chan3.state(), L2capChannel::State::kRunning);
3139 
3140   PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(proxy, kHandle));
3141 
3142   EXPECT_EQ(events_received, 2);
3143   EXPECT_EQ(chan1.state(), L2capChannel::State::kClosed);
3144   EXPECT_EQ(chan2.state(), L2capChannel::State::kRunning);
3145   EXPECT_EQ(chan3.state(), L2capChannel::State::kClosed);
3146 
3147   // Confirm L2CAP_DISCONNECTION_RSP packet does not result in another event.
3148   PW_TEST_EXPECT_OK(SendL2capDisconnectRsp(
3149       proxy, AclTransportType::kLe, kHandle, kStartingCid, kStartingCid));
3150   EXPECT_EQ(events_received, 2);
3151 }
3152 
TEST_F(ProxyHostConnectionEventTest,L2capDisconnectionRspFromHostClosesChannels)3153 TEST_F(ProxyHostConnectionEventTest,
3154        L2capDisconnectionRspFromHostClosesChannels) {
3155   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
3156       [](H4PacketWithH4&&) {});
3157   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
3158       [](H4PacketWithHci&&) {});
3159   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
3160                               std::move(send_to_controller_fn),
3161                               /*le_acl_credits_to_reserve=*/0,
3162                               /*br_edr_acl_credits_to_reserve=*/0);
3163 
3164   constexpr uint16_t kHandle = 0x123;
3165   constexpr uint16_t kStartingSourceCid = 0x111;
3166   constexpr uint16_t kStartingDestinationCid = 0x211;
3167   int events_received = 0;
3168   auto event_fn = [&events_received](L2capChannelEvent event) {
3169     ++events_received;
3170     EXPECT_EQ(event, L2capChannelEvent::kChannelClosedByOther);
3171   };
3172   BasicL2capChannel chan1 =
3173       BuildBasicL2capChannel(proxy,
3174                              {.handle = kHandle,
3175                               .local_cid = kStartingDestinationCid,
3176                               .remote_cid = kStartingSourceCid,
3177                               .event_fn = event_fn});
3178   BasicL2capChannel chan2 =
3179       BuildBasicL2capChannel(proxy,
3180                              {.handle = kHandle,
3181                               .local_cid = kStartingDestinationCid + 1,
3182                               .remote_cid = kStartingSourceCid + 1,
3183                               .event_fn = event_fn});
3184   BasicL2capChannel chan3 =
3185       BuildBasicL2capChannel(proxy,
3186                              {.handle = kHandle,
3187                               .local_cid = kStartingDestinationCid + 2,
3188                               .remote_cid = kStartingSourceCid + 2,
3189                               .event_fn = event_fn});
3190 
3191   EXPECT_EQ(chan1.state(), L2capChannel::State::kRunning);
3192   EXPECT_EQ(chan2.state(), L2capChannel::State::kRunning);
3193   EXPECT_EQ(chan3.state(), L2capChannel::State::kRunning);
3194 
3195   // Close chan1's & chan2's underlying L2CAP connections.
3196   PW_TEST_EXPECT_OK(
3197       SendL2capDisconnectRsp(proxy,
3198                              AclTransportType::kLe,
3199                              kHandle,
3200                              /*source_cid=*/kStartingSourceCid,
3201                              /*destination_cid=*/kStartingDestinationCid));
3202   PW_TEST_EXPECT_OK(
3203       SendL2capDisconnectRsp(proxy,
3204                              AclTransportType::kLe,
3205                              kHandle,
3206                              /*source_cid=*/kStartingSourceCid + 2,
3207                              /*destination_cid=*/kStartingDestinationCid + 2));
3208 
3209   EXPECT_EQ(events_received, 2);
3210   EXPECT_EQ(chan1.state(), L2capChannel::State::kClosed);
3211   EXPECT_EQ(chan2.state(), L2capChannel::State::kRunning);
3212   EXPECT_EQ(chan3.state(), L2capChannel::State::kClosed);
3213 
3214   // Confirm HCI disconnection only closes remaining channel.
3215   PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(proxy, kHandle));
3216   EXPECT_EQ(chan2.state(), L2capChannel::State::kClosed);
3217   EXPECT_EQ(events_received, 3);
3218 }
3219 
TEST_F(ProxyHostConnectionEventTest,HciDisconnectionFromHostClosesChannels)3220 TEST_F(ProxyHostConnectionEventTest, HciDisconnectionFromHostClosesChannels) {
3221   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
3222       [](H4PacketWithH4&&) {});
3223   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
3224       [](H4PacketWithHci&&) {});
3225   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
3226                               std::move(send_to_controller_fn),
3227                               /*le_acl_credits_to_reserve=*/0,
3228                               /*br_edr_acl_credits_to_reserve=*/0);
3229 
3230   constexpr uint16_t kHandle = 0x123;
3231   constexpr uint16_t kStartingCid = 0x111;
3232   int events_received = 0;
3233   auto event_fn = [&events_received](L2capChannelEvent event) {
3234     ++events_received;
3235     EXPECT_EQ(event, L2capChannelEvent::kChannelClosedByOther);
3236   };
3237   BasicL2capChannel chan1 = BuildBasicL2capChannel(proxy,
3238                                                    {.handle = kHandle,
3239                                                     .local_cid = kStartingCid,
3240                                                     .remote_cid = kStartingCid,
3241                                                     .event_fn = event_fn});
3242   BasicL2capChannel chan2 =
3243       BuildBasicL2capChannel(proxy,
3244                              {.handle = kHandle + 1,
3245                               .local_cid = kStartingCid + 1,
3246                               .remote_cid = kStartingCid + 1,
3247                               .event_fn = event_fn});
3248   BasicL2capChannel chan3 =
3249       BuildBasicL2capChannel(proxy,
3250                              {.handle = kHandle,
3251                               .local_cid = kStartingCid + 2,
3252                               .remote_cid = kStartingCid + 2,
3253                               .event_fn = event_fn});
3254 
3255   EXPECT_EQ(chan1.state(), L2capChannel::State::kRunning);
3256   EXPECT_EQ(chan2.state(), L2capChannel::State::kRunning);
3257   EXPECT_EQ(chan3.state(), L2capChannel::State::kRunning);
3258 
3259   PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(
3260       proxy, kHandle, /*direction=*/Direction::kFromHost));
3261 
3262   EXPECT_EQ(chan1.state(), L2capChannel::State::kClosed);
3263   EXPECT_EQ(chan2.state(), L2capChannel::State::kRunning);
3264   EXPECT_EQ(chan3.state(), L2capChannel::State::kClosed);
3265   EXPECT_EQ(events_received, 2);
3266 }
3267 
TEST_F(ProxyHostConnectionEventTest,L2capDisconnectionRspFromControllerClosesChannels)3268 TEST_F(ProxyHostConnectionEventTest,
3269        L2capDisconnectionRspFromControllerClosesChannels) {
3270   pw::Function<void(H4PacketWithH4 && packet)> send_to_controller_fn(
3271       [](H4PacketWithH4&&) {});
3272   pw::Function<void(H4PacketWithHci && packet)> send_to_host_fn(
3273       [](H4PacketWithHci&&) {});
3274   ProxyHost proxy = ProxyHost(std::move(send_to_host_fn),
3275                               std::move(send_to_controller_fn),
3276                               /*le_acl_credits_to_reserve=*/0,
3277                               /*br_edr_acl_credits_to_reserve=*/0);
3278 
3279   constexpr uint16_t kHandle = 0x123;
3280   constexpr uint16_t kStartingCid = 0x111;
3281   int events_received = 0;
3282   auto event_fn = [&events_received](L2capChannelEvent event) {
3283     ++events_received;
3284     EXPECT_EQ(event, L2capChannelEvent::kChannelClosedByOther);
3285   };
3286   BasicL2capChannel chan1 = BuildBasicL2capChannel(proxy,
3287                                                    {.handle = kHandle,
3288                                                     .local_cid = kStartingCid,
3289                                                     .remote_cid = kStartingCid,
3290                                                     .event_fn = event_fn});
3291   BasicL2capChannel chan2 =
3292       BuildBasicL2capChannel(proxy,
3293                              {.handle = kHandle,
3294                               .local_cid = kStartingCid + 1,
3295                               .remote_cid = kStartingCid + 1,
3296                               .event_fn = event_fn});
3297   BasicL2capChannel chan3 =
3298       BuildBasicL2capChannel(proxy,
3299                              {.handle = kHandle,
3300                               .local_cid = kStartingCid + 2,
3301                               .remote_cid = kStartingCid + 2,
3302                               .event_fn = event_fn});
3303 
3304   EXPECT_EQ(chan1.state(), L2capChannel::State::kRunning);
3305   EXPECT_EQ(chan2.state(), L2capChannel::State::kRunning);
3306   EXPECT_EQ(chan3.state(), L2capChannel::State::kRunning);
3307 
3308   // Close chan1's & chan2's underlying L2CAP connections.
3309   PW_TEST_EXPECT_OK(
3310       SendL2capDisconnectRsp(proxy,
3311                              AclTransportType::kLe,
3312                              kHandle,
3313                              kStartingCid,
3314                              kStartingCid,
3315                              /*direction=*/Direction::kFromController));
3316   PW_TEST_EXPECT_OK(
3317       SendL2capDisconnectRsp(proxy,
3318                              AclTransportType::kLe,
3319                              kHandle,
3320                              kStartingCid + 2,
3321                              kStartingCid + 2,
3322                              /*direction=*/Direction::kFromController));
3323 
3324   EXPECT_EQ(events_received, 2);
3325   EXPECT_EQ(chan1.state(), L2capChannel::State::kClosed);
3326   EXPECT_EQ(chan2.state(), L2capChannel::State::kRunning);
3327   EXPECT_EQ(chan3.state(), L2capChannel::State::kClosed);
3328 
3329   // Confirm HCI disconnection only closes remaining channel.
3330   PW_TEST_EXPECT_OK(SendDisconnectionCompleteEvent(proxy, kHandle));
3331   EXPECT_EQ(chan2.state(), L2capChannel::State::kClosed);
3332   EXPECT_EQ(events_received, 3);
3333 }
3334 
3335 // ########## AclFragTest
3336 
3337 class AclFragTest : public ProxyHostTest {
3338  protected:
3339   static constexpr uint16_t kHandle = 0x4AD;
3340   static constexpr uint16_t kLocalCid = 0xC1D;
3341 
3342   int packets_sent_to_host = 0;
3343   int packets_sent_to_controller = 0;
3344 
GetProxy()3345   ProxyHost GetProxy() {
3346     // We can't add a ProxyHost member because it makes the test fixture too
3347     // large, so we provide a helper function instead.
3348     return ProxyHost(pw::bind_member<&AclFragTest::SendToHost>(this),
3349                      pw::bind_member<&AclFragTest::SendToController>(this),
3350                      /*le_acl_credits_to_reserve=*/0,
3351                      /*br_edr_acl_credits_to_reserve=*/0);
3352   }
3353 
3354   std::vector<multibuf::MultiBuf> payloads_from_controller;
3355 
GetL2capChannel(ProxyHost & proxy)3356   BasicL2capChannel GetL2capChannel(ProxyHost& proxy) {
3357     return BuildBasicL2capChannel(
3358         proxy,
3359         BasicL2capParameters{
3360             .handle = kHandle,
3361             .local_cid = kLocalCid,
3362             .remote_cid = 0x123,
3363             .transport = AclTransportType::kLe,
3364             .payload_from_controller_fn =
3365                 [this](multibuf::MultiBuf&& buffer) {
3366                   payloads_from_controller.emplace_back(std::move(buffer));
3367                   return std::nullopt;  // Consume
3368                 },
3369         });
3370   }
3371 
ExpectPayloadsFromController(std::initializer_list<ConstByteSpan> expected_payloads)3372   void ExpectPayloadsFromController(
3373       std::initializer_list<ConstByteSpan> expected_payloads) {
3374     EXPECT_EQ(payloads_from_controller.size(), expected_payloads.size());
3375     if (payloads_from_controller.size() != expected_payloads.size()) {
3376       return;
3377     }
3378 
3379     auto payloads_iter = payloads_from_controller.begin();
3380     for (ConstByteSpan expected : expected_payloads) {
3381       std::optional<pw::ByteSpan> payload = (payloads_iter++)->ContiguousSpan();
3382       PW_CHECK(payload.has_value());
3383       EXPECT_TRUE(std::equal(
3384           payload->begin(), payload->end(), expected.begin(), expected.end()));
3385     }
3386   }
3387 
VerifyNormalOperationAfterRecombination(ProxyHost & proxy)3388   void VerifyNormalOperationAfterRecombination(ProxyHost& proxy) {
3389     // Verify things work normally after recombination ends.
3390     static constexpr std::array<uint8_t, 4> kPayload = {'D', 'o', 'n', 'e'};
3391     payloads_from_controller.clear();
3392     SendL2capBFrame(proxy, kHandle, kPayload, kPayload.size(), kLocalCid);
3393     ExpectPayloadsFromController({
3394         as_bytes(span(kPayload)),
3395     });
3396   }
3397 
3398  private:
SendToHost(H4PacketWithHci &&)3399   void SendToHost(H4PacketWithHci&& /*packet*/) { ++packets_sent_to_host; }
3400 
SendToController(H4PacketWithH4 &&)3401   void SendToController(H4PacketWithH4&& /*packet*/) {
3402     ++packets_sent_to_controller;
3403   }
3404 };
3405 
TEST_F(AclFragTest,AclBiggerThanL2capDropped)3406 TEST_F(AclFragTest, AclBiggerThanL2capDropped) {
3407   ProxyHost proxy = GetProxy();
3408   BasicL2capChannel channel = GetL2capChannel(proxy);
3409 
3410   // Send an ACL packet with more data than L2CAP header indicates.
3411   static constexpr std::array<uint8_t, 4> kPayload{};
3412   SendL2capBFrame(proxy, kHandle, kPayload, 1, kLocalCid);
3413 
3414   // Should be dropped.
3415   EXPECT_EQ(packets_sent_to_host, 0);
3416   ExpectPayloadsFromController({});
3417 }
3418 
TEST_F(AclFragTest,RecombinationWorksWithEmptyFirstPayload)3419 TEST_F(AclFragTest, RecombinationWorksWithEmptyFirstPayload) {
3420   ProxyHost proxy = GetProxy();
3421   BasicL2capChannel channel = GetL2capChannel(proxy);
3422 
3423   static constexpr std::array<uint8_t, 4> kPayload = {0xA1, 0xB2, 0xC3, 0xD2};
3424 
3425   // Fragment 1: ACL Header + L2CAP B-Frame Header + (no payload)
3426   PW_LOG_INFO("Sending frag 1: ACL + L2CAP header");
3427   SendL2capBFrame(proxy, kHandle, {}, kPayload.size(), kLocalCid);
3428 
3429   // Fragment 2: ACL Header + Payload frag 2
3430   PW_LOG_INFO("Sending frag 2: ACL(CONT) + payload2");
3431   SendAclContinuingFrag(proxy, kHandle, kPayload);
3432 
3433   EXPECT_EQ(packets_sent_to_host, 0);
3434   ExpectPayloadsFromController({
3435       as_bytes(span(kPayload)),
3436   });
3437 
3438   VerifyNormalOperationAfterRecombination(proxy);
3439 }
3440 
TEST_F(AclFragTest,RecombinationWorksWithSplitPayloads)3441 TEST_F(AclFragTest, RecombinationWorksWithSplitPayloads) {
3442   ProxyHost proxy = GetProxy();
3443   BasicL2capChannel channel = GetL2capChannel(proxy);
3444 
3445   static constexpr std::array<uint8_t, 2> kPayloadFrag1 = {0xA1, 0xB2};
3446   static constexpr std::array<uint8_t, 2> kPayloadFrag2 = {0xC3, 0xD2};
3447   static constexpr std::array<uint8_t, 4> kPayload = {0xA1, 0xB2, 0xC3, 0xD2};
3448 
3449   constexpr int kNumIter = 4;
3450 
3451   for (int i = 0; i < kNumIter; ++i) {
3452     // Fragment 1: ACL Header + L2CAP B-Frame Header + Payload frag 1
3453     PW_LOG_INFO("Sending frag 1: ACL + L2CAP header + payload1");
3454     SendL2capBFrame(proxy, kHandle, kPayloadFrag1, kPayload.size(), kLocalCid);
3455 
3456     // Fragment 2: ACL Header + Payload frag 2
3457     PW_LOG_INFO("Sending frag 2: ACL(CONT) + payload2");
3458     SendAclContinuingFrag(proxy, kHandle, kPayloadFrag2);
3459   }
3460 
3461   EXPECT_EQ(packets_sent_to_host, 0);
3462   ExpectPayloadsFromController({
3463       as_bytes(span(kPayload)),
3464       as_bytes(span(kPayload)),
3465       as_bytes(span(kPayload)),
3466       as_bytes(span(kPayload)),
3467   });
3468 
3469   VerifyNormalOperationAfterRecombination(proxy);
3470 }
3471 
TEST_F(AclFragTest,UnexpectedContinuingFragment)3472 TEST_F(AclFragTest, UnexpectedContinuingFragment) {
3473   ProxyHost proxy = GetProxy();
3474   BasicL2capChannel channel = GetL2capChannel(proxy);
3475 
3476   static constexpr std::array<uint8_t, 4> kPayload = {0xA1, 0xB2, 0xC3, 0xD2};
3477 
3478   // Send an unexpected CONTINUING_FRAGMENT
3479   PW_LOG_INFO("Sending frag 1: ACL(CONT) + payload");
3480   SendAclContinuingFrag(proxy, kHandle, kPayload);
3481 
3482   ExpectPayloadsFromController({});
3483   EXPECT_EQ(packets_sent_to_host, 1);  // Should be passed on to host
3484 
3485   VerifyNormalOperationAfterRecombination(proxy);
3486 }
3487 
TEST_F(AclFragTest,UnexpectedFirstFragment)3488 TEST_F(AclFragTest, UnexpectedFirstFragment) {
3489   ProxyHost proxy = GetProxy();
3490   BasicL2capChannel channel = GetL2capChannel(proxy);
3491 
3492   static constexpr std::array<uint8_t, 2> kPayloadFrag1 = {0xA1, 0xB2};
3493   static constexpr std::array<uint8_t, 2> kPayloadFrag2 = {0xC3, 0xD2};
3494   static constexpr std::array<uint8_t, 4> kPayload = {0xA1, 0xB2, 0xC3, 0xD2};
3495 
3496   // PDU A: Fragment 1: Start recombination by sending first fragment.
3497   PW_LOG_INFO("Sending frag 1: ACL + L2CAP header + payload1");
3498   SendL2capBFrame(proxy, kHandle, {}, 100, kLocalCid);
3499 
3500   // We never send the 100 byte payload here.
3501 
3502   // So this new first-fragment is unexpected:
3503   // PDU B: Fragment 1: ACL Header + L2CAP B-Frame Header + Payload frag 1
3504   PW_LOG_INFO("Sending frag 1: ACL + L2CAP header + payload1");
3505   SendL2capBFrame(proxy, kHandle, kPayloadFrag1, kPayload.size(), kLocalCid);
3506 
3507   // PDU B: Fragment 2: ACL Header + Payload frag 2
3508   PW_LOG_INFO("Sending frag 2: ACL(CONT) + payload2");
3509   SendAclContinuingFrag(proxy, kHandle, kPayloadFrag2);
3510 
3511   // Nothing should be sent to the host. The first fragment of PDU A is dropped.
3512   EXPECT_EQ(packets_sent_to_host, 0);
3513 
3514   // PDU B is delivered.
3515   ExpectPayloadsFromController({
3516       as_bytes(span(kPayload)),
3517   });
3518 
3519   VerifyNormalOperationAfterRecombination(proxy);
3520 }
3521 
TEST_F(AclFragTest,ContinuingFragmentTooLarge)3522 TEST_F(AclFragTest, ContinuingFragmentTooLarge) {
3523   ProxyHost proxy = GetProxy();
3524   BasicL2capChannel channel = GetL2capChannel(proxy);
3525 
3526   static constexpr std::array<uint8_t, 2> kPayloadFrag1 = {0xA1, 0xB2};
3527   static constexpr std::array<uint8_t, 5> kPayloadFrag2TooBig = {
3528       0xC3, 0xD2, 0xBA, 0xAA, 0xAD};
3529   static constexpr std::array<uint8_t, 4> kPayload = {0xA1, 0xB2, 0xC3, 0xD2};
3530 
3531   // Fragment 1: ACL Header + L2CAP B-Frame Header + Payload frag 1
3532   PW_LOG_INFO("Sending frag 1: ACL + L2CAP header + payload1");
3533   SendL2capBFrame(proxy, kHandle, kPayloadFrag1, kPayload.size(), kLocalCid);
3534 
3535   // Fragment 2: ACL Header + Payload frag 2
3536   PW_LOG_INFO("Sending frag 2: ACL(CONT) + payload2 (too big)");
3537   SendAclContinuingFrag(proxy, kHandle, kPayloadFrag2TooBig);
3538 
3539   ExpectPayloadsFromController({});
3540 
3541   // This was for a channel owned by the proxy so it should have been dropped.
3542   EXPECT_EQ(packets_sent_to_host, 0);
3543 
3544   VerifyNormalOperationAfterRecombination(proxy);
3545 }
3546 
TEST_F(AclFragTest,CanReceiveUnfragmentedPduOnOneChannelWhileRecombiningOnAnother)3547 TEST_F(AclFragTest,
3548        CanReceiveUnfragmentedPduOnOneChannelWhileRecombiningOnAnother) {
3549   ProxyHost proxy = GetProxy();
3550 
3551   // Channel 1
3552   static constexpr std::array<uint8_t, 2> kPayload1Frag1 = {0xA1, 0xB2};
3553   static constexpr std::array<uint8_t, 2> kPayload1Frag2 = {0xC3, 0xD2};
3554   static constexpr std::array<uint8_t, 4> kPayload1 = {0xA1, 0xB2, 0xC3, 0xD2};
3555 
3556   int channel1_sends_called = 0;
3557   BasicL2capChannel channel = BuildBasicL2capChannel(
3558       proxy,
3559       BasicL2capParameters{
3560           .handle = kHandle,
3561           .local_cid = kLocalCid,
3562           .remote_cid = 0x123,
3563           .transport = AclTransportType::kLe,
3564           .payload_from_controller_fn =
3565               [&channel1_sends_called](multibuf::MultiBuf&& buffer) {
3566                 ++channel1_sends_called;
3567                 std::optional<pw::ByteSpan> payload = buffer.ContiguousSpan();
3568                 ConstByteSpan expected_bytes = as_bytes(span(kPayload1));
3569                 EXPECT_TRUE(payload.has_value());
3570                 EXPECT_TRUE(std::equal(payload->begin(),
3571                                        payload->end(),
3572                                        expected_bytes.begin(),
3573                                        expected_bytes.end()));
3574                 return std::nullopt;
3575               },
3576       });
3577 
3578   // Channel 2
3579   static constexpr uint16_t kHandle2 = 0x4D2;
3580   static constexpr uint16_t kLocalCid2 = 0xC2D;
3581   static constexpr std::array<uint8_t, 4> kPayload2 = {0x33, 0x66, 0x99, 0xCC};
3582 
3583   int channel2_sends_called = 0;
3584   BasicL2capChannel channel2 = BuildBasicL2capChannel(
3585       proxy,
3586       BasicL2capParameters{
3587           .handle = kHandle2,
3588           .local_cid = kLocalCid2,
3589           .remote_cid = 0x321,
3590           .transport = AclTransportType::kLe,
3591           .payload_from_controller_fn =
3592               [&channel2_sends_called](multibuf::MultiBuf&& buffer) {
3593                 ++channel2_sends_called;
3594                 std::optional<pw::ByteSpan> payload = buffer.ContiguousSpan();
3595                 ConstByteSpan expected_bytes = as_bytes(span(kPayload2));
3596                 EXPECT_TRUE(payload.has_value());
3597                 EXPECT_TRUE(std::equal(payload->begin(),
3598                                        payload->end(),
3599                                        expected_bytes.begin(),
3600                                        expected_bytes.end()));
3601                 return std::nullopt;
3602               },
3603       });
3604 
3605   // Channel 1: Fragment 1: ACL Header + L2CAP B-Frame Header + Payload frag 1
3606   PW_LOG_INFO("Sending frag 1: ACL + L2CAP header + payload1");
3607   SendL2capBFrame(proxy, kHandle, kPayload1Frag1, kPayload1.size(), kLocalCid);
3608 
3609   // Channel 2: Send full PDU
3610   SendL2capBFrame(proxy, kHandle2, kPayload2, kPayload2.size(), kLocalCid2);
3611   EXPECT_EQ(channel2_sends_called, 1);
3612 
3613   // Channel 1: Fragment 2: ACL Header + Payload frag 2
3614   PW_LOG_INFO("Sending frag 2: ACL(CONT) + payload2");
3615   SendAclContinuingFrag(proxy, kHandle, kPayload1Frag2);
3616 
3617   EXPECT_EQ(channel1_sends_called, 1);
3618   EXPECT_EQ(packets_sent_to_host, 0);
3619 }
3620 
3621 }  // namespace
3622 }  // namespace pw::bluetooth::proxy
3623