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_async_fuchsia/dispatcher.h>
16
17 #include "pw_bluetooth_sapphire/fuchsia/host/socket/socket_factory.h"
18 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel.h"
19 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_manager.h"
20 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_manager_mock_controller_test_fixture.h"
21 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
22 #include "pw_bluetooth_sapphire/internal/host/l2cap/test_packets.h"
23 #include "pw_bluetooth_sapphire/internal/host/testing/loop_fixture.h"
24 #include "pw_bluetooth_sapphire/internal/host/testing/mock_controller.h"
25 #include "pw_unit_test/framework.h"
26
27 namespace bt::socket {
28 namespace {
29
30 using namespace bt::testing;
31
32 using TestingBase = l2cap::ChannelManagerMockControllerTest;
33
34 // This test harness provides test cases for interactions between SocketFactory
35 // and the L2cap layer.
36 class SocketFactoryL2capIntegrationTest : public TestLoopFixture,
37 public TestingBase {
38 public:
SocketFactoryL2capIntegrationTest()39 SocketFactoryL2capIntegrationTest()
40 : TestingBase(dispatcher_), dispatcher_(dispatcher()) {}
41 ~SocketFactoryL2capIntegrationTest() override = default;
42
43 protected:
SetUp()44 void SetUp() override {
45 TestingBase::Initialize();
46 socket_factory_ = std::make_unique<socket::SocketFactory<l2cap::Channel>>();
47 }
48
TearDown()49 void TearDown() override {
50 socket_factory_.reset();
51 TestingBase::DeleteChannelManager();
52 RunLoopUntilIdle();
53 DeleteTransport();
54 }
55
MakeSocketForChannel(l2cap::Channel::WeakPtr channel)56 zx::socket MakeSocketForChannel(l2cap::Channel::WeakPtr channel) {
57 return socket_factory_->MakeSocketForChannel(std::move(channel));
58 }
59
60 private:
61 std::unique_ptr<socket::SocketFactory<l2cap::Channel>> socket_factory_;
62 pw::async_fuchsia::FuchsiaDispatcher dispatcher_;
63
64 BT_DISALLOW_COPY_ASSIGN_AND_MOVE(SocketFactoryL2capIntegrationTest);
65 };
66
TEST_F(SocketFactoryL2capIntegrationTest,InboundL2capSocket)67 TEST_F(SocketFactoryL2capIntegrationTest, InboundL2capSocket) {
68 constexpr l2cap::Psm kPsm = l2cap::kAVDTP;
69 constexpr l2cap::ChannelId kLocalId = 0x0040;
70 constexpr l2cap::ChannelId kRemoteId = 0x9042;
71 constexpr hci_spec::ConnectionHandle kLinkHandle = 0x0001;
72
73 QueueAclConnection(kLinkHandle);
74
75 l2cap::Channel::WeakPtr channel;
76 auto chan_cb = [&](auto cb_chan) {
77 EXPECT_EQ(kLinkHandle, cb_chan->link_handle());
78 channel = std::move(cb_chan);
79 };
80 chanmgr()->RegisterService(kPsm, kChannelParameters, std::move(chan_cb));
81 RunLoopUntilIdle();
82
83 QueueInboundL2capConnection(kLinkHandle, kPsm, kLocalId, kRemoteId);
84
85 RunLoopUntilIdle();
86 ASSERT_TRUE(channel.is_alive());
87 zx::socket sock = MakeSocketForChannel(channel);
88
89 // Test basic channel<->socket interaction by verifying that an ACL packet
90 // gets routed to socket
91 test_device()->SendACLDataChannelPacket(StaticByteBuffer(
92 // ACL data header (handle: 1, length 8)
93 0x01,
94 0x00,
95 0x08,
96 0x00,
97 // L2CAP B-frame: (length: 4, channel-id: 0x0040 (kLocalId))
98 0x04,
99 0x00,
100 0x40,
101 0x00,
102 // L2CAP payload
103 't',
104 'e',
105 's',
106 't'));
107
108 // Run until the packet is written to the socket buffer.
109 RunLoopUntilIdle();
110
111 // Allocate a larger buffer than the number of SDU bytes we expect (which is
112 // 4).
113 StaticByteBuffer<10> socket_bytes;
114 size_t bytes_read;
115 zx_status_t status = sock.read(
116 0, socket_bytes.mutable_data(), socket_bytes.size(), &bytes_read);
117 EXPECT_EQ(ZX_OK, status);
118 ASSERT_EQ(4u, bytes_read);
119 EXPECT_EQ("test", socket_bytes.view(0, bytes_read).AsString());
120
121 const char write_data[81] = "";
122
123 // Test outbound data fragments using |kMaxDataPacketLength|.
124 constexpr size_t kFirstFragmentPayloadSize =
125 kMaxDataPacketLength - sizeof(l2cap::BasicHeader);
126 const StaticByteBuffer<sizeof(hci_spec::ACLDataHeader) +
127 sizeof(l2cap::BasicHeader) + kFirstFragmentPayloadSize>
128 kFirstFragment(
129 // ACL data header (handle: 1, length 64)
130 0x01,
131 0x00,
132 0x40,
133 0x00,
134 // L2CAP B-frame: (length: 80, channel-id: 0x9042 (kRemoteId))
135 0x50,
136 0x00,
137 0x42,
138 0x90,
139 // L2CAP payload (fragmented)
140 0xf0,
141 0x9f,
142 0x9a,
143 0x82,
144 0xf0,
145 0x9f,
146 0x9a,
147 0x83,
148 0xf0,
149 0x9f,
150 0x9a,
151 0x84,
152 0xf0,
153 0x9f,
154 0x9a,
155 0x85,
156 0xf0,
157 0x9f,
158 0x9a,
159 0x86,
160 0xf0,
161 0x9f,
162 0x9a,
163 0x88,
164 0xf0,
165 0x9f,
166 0x9a,
167 0x87,
168 0xf0,
169 0x9f,
170 0x9a,
171 0x88,
172 0xf0,
173 0x9f,
174 0x9a,
175 0x89,
176 0xf0,
177 0x9f,
178 0x9a,
179 0x8a,
180 0xf0,
181 0x9f,
182 0x9a,
183 0x8b,
184 0xf0,
185 0x9f,
186 0x9a,
187 0x8c,
188 0xf0,
189 0x9f,
190 0x9a,
191 0x8e,
192 0xf0,
193 0x9f,
194 0x9a,
195 0x9d,
196 0xf0,
197 0x9f,
198 0x9a,
199 0x9e);
200
201 constexpr size_t kSecondFragmentPayloadSize =
202 sizeof(write_data) - 1 - kFirstFragmentPayloadSize;
203 const StaticByteBuffer<sizeof(hci_spec::ACLDataHeader) +
204 kSecondFragmentPayloadSize>
205 kSecondFragment(
206 // ACL data header (handle: 1, pbf: continuing fr., length: 20)
207 0x01,
208 0x10,
209 0x14,
210 0x00,
211 // L2CAP payload (final fragment)
212 0xf0,
213 0x9f,
214 0x9a,
215 0x9f,
216 0xf0,
217 0x9f,
218 0x9a,
219 0xa0,
220 0xf0,
221 0x9f,
222 0x9a,
223 0xa1,
224 0xf0,
225 0x9f,
226 0x9b,
227 0xa4,
228 0xf0,
229 0x9f,
230 0x9b,
231 0xb2);
232
233 // The 80-byte write should be fragmented over 64- and 20-byte HCI payloads in
234 // order to send it to the controller.
235 EXPECT_ACL_PACKET_OUT(test_device(), kFirstFragment);
236 EXPECT_ACL_PACKET_OUT(test_device(), kSecondFragment);
237
238 size_t bytes_written = 0;
239 // Write 80 outbound bytes to the socket buffer.
240 status = sock.write(0, write_data, sizeof(write_data) - 1, &bytes_written);
241 EXPECT_EQ(ZX_OK, status);
242 EXPECT_EQ(80u, bytes_written);
243
244 // Run until the data is flushed out to the MockController.
245 RunLoopUntilIdle();
246 EXPECT_TRUE(test_device()->AllExpectedDataPacketsSent());
247
248 // Synchronously closes channels & sockets.
249 chanmgr()->RemoveConnection(kLinkHandle);
250 acl_data_channel()->UnregisterConnection(kLinkHandle);
251 acl_data_channel()->ClearControllerPacketCount(kLinkHandle);
252
253 // try resending data now that connection is closed
254 bytes_written = 0;
255 status = sock.write(0, write_data, sizeof(write_data) - 1, &bytes_written);
256
257 EXPECT_EQ(ZX_ERR_PEER_CLOSED, status);
258 EXPECT_EQ(0u, bytes_written);
259
260 // no packets should be sent
261 RunLoopUntilIdle();
262 }
263
TEST_F(SocketFactoryL2capIntegrationTest,OutboundL2capSocket)264 TEST_F(SocketFactoryL2capIntegrationTest, OutboundL2capSocket) {
265 constexpr l2cap::Psm kPsm = l2cap::kAVCTP;
266 constexpr l2cap::ChannelId kLocalId = 0x0040;
267 constexpr l2cap::ChannelId kRemoteId = 0x9042;
268 constexpr hci_spec::ConnectionHandle kLinkHandle = 0x0001;
269
270 QueueAclConnection(kLinkHandle);
271 RunLoopUntilIdle();
272
273 EXPECT_TRUE(test_device()->AllExpectedDataPacketsSent());
274
275 l2cap::Channel::WeakPtr chan;
276 auto chan_cb = [&](auto cb_chan) {
277 EXPECT_EQ(kLinkHandle, cb_chan->link_handle());
278 chan = std::move(cb_chan);
279 };
280 QueueOutboundL2capConnection(
281 kLinkHandle, kPsm, kLocalId, kRemoteId, std::move(chan_cb));
282
283 RunLoopUntilIdle();
284 EXPECT_TRUE(test_device()->AllExpectedDataPacketsSent());
285 // We should have opened a channel successfully.
286 ASSERT_TRUE(chan.is_alive());
287 zx::socket sock = MakeSocketForChannel(chan);
288
289 // Test basic channel<->socket interaction by verifying that an ACL packet
290 // gets routed to socket.
291 test_device()->SendACLDataChannelPacket(StaticByteBuffer(
292 // ACL data header (handle: 1, length 8)
293 0x01,
294 0x00,
295 0x08,
296 0x00,
297 // L2CAP B-frame: (length: 4, channel-id: 0x0040 (kLocalId))
298 0x04,
299 0x00,
300 0x40,
301 0x00,
302 // L2CAP payload
303 't',
304 'e',
305 's',
306 't'));
307
308 // Run until the packet is written to the socket buffer.
309 RunLoopUntilIdle();
310
311 // Allocate a larger buffer than the number of SDU bytes we expect (which is
312 // 4).
313 StaticByteBuffer<10> socket_bytes;
314 size_t bytes_read;
315 zx_status_t status = sock.read(
316 0, socket_bytes.mutable_data(), socket_bytes.size(), &bytes_read);
317 EXPECT_EQ(ZX_OK, status);
318 ASSERT_EQ(4u, bytes_read);
319 EXPECT_EQ("test", socket_bytes.view(0, bytes_read).AsString());
320
321 EXPECT_ACL_PACKET_OUT(test_device(),
322 l2cap::testing::AclDisconnectionReq(
323 NextCommandId(), kLinkHandle, kLocalId, kRemoteId));
324 }
325
326 } // namespace
327 } // namespace bt::socket
328