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_sapphire/fuchsia/host/socket/socket_channel_relay.h"
16
17 #include <lib/async-loop/cpp/loop.h>
18 #include <lib/async-loop/default.h>
19 #include <pw_async_fuchsia/dispatcher.h>
20
21 #include <memory>
22 #include <type_traits>
23
24 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
25 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
26 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_channel.h"
27 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
28 #include "pw_unit_test/framework.h"
29
30 namespace bt::socket {
31 namespace {
32
33 // We'll test the template just for L2CAP channels.
34 using RelayT = SocketChannelRelay<l2cap::Channel>;
35 constexpr size_t kDefaultSocketWriteQueueLimitFrames = 2;
36
37 class SocketChannelRelayTest : public ::testing::Test {
38 public:
SocketChannelRelayTest()39 SocketChannelRelayTest()
40 : loop_(&kAsyncLoopConfigAttachToCurrentThread),
41 pw_dispatcher_(dispatcher()) {
42 EXPECT_EQ(ASYNC_LOOP_RUNNABLE, loop_.GetState());
43
44 constexpr l2cap::ChannelId kDynamicChannelIdMin = 0x0040;
45 constexpr l2cap::ChannelId kRemoteChannelId = 0x0050;
46 constexpr hci_spec::ConnectionHandle kDefaultConnectionHandle = 0x0001;
47 channel_ =
48 std::make_unique<l2cap::testing::FakeChannel>(kDynamicChannelIdMin,
49 kRemoteChannelId,
50 kDefaultConnectionHandle,
51 bt::LinkType::kACL);
52
53 const auto socket_status =
54 zx::socket::create(ZX_SOCKET_DATAGRAM, &local_socket_, &remote_socket_);
55 local_socket_unowned_ = zx::unowned_socket(local_socket_);
56 EXPECT_EQ(ZX_OK, socket_status);
57 }
58
pw_dispatcher()59 pw::async::Dispatcher& pw_dispatcher() { return pw_dispatcher_; }
60
61 // Writes data on |local_socket| until the socket is full, or an error occurs.
62 // Returns the number of bytes written if the socket fills, and zero
63 // otherwise.
StuffSocket()64 [[nodiscard]] size_t StuffSocket() {
65 size_t n_total_bytes_written = 0;
66 zx_status_t write_res;
67 // Fill the socket buffer completely, while minimzing the number of
68 // syscalls required.
69 for (const auto spam_size_bytes : {65536,
70 32768,
71 16384,
72 8192,
73 4096,
74 2048,
75 1024,
76 512,
77 256,
78 128,
79 64,
80 32,
81 16,
82 8,
83 4,
84 2,
85 1}) {
86 DynamicByteBuffer spam_data(spam_size_bytes);
87 spam_data.Fill(kSpamChar);
88 do {
89 size_t n_iter_bytes_written = 0;
90 write_res = local_socket_unowned_->write(
91 0, spam_data.data(), spam_data.size(), &n_iter_bytes_written);
92 if (write_res != ZX_OK && write_res != ZX_ERR_SHOULD_WAIT) {
93 bt_log(ERROR,
94 "l2cap",
95 "Failure in zx_socket_write(): %s",
96 zx_status_get_string(write_res));
97 return 0;
98 }
99 n_total_bytes_written += n_iter_bytes_written;
100 } while (write_res == ZX_OK);
101 }
102 return n_total_bytes_written;
103 }
104
105 // Reads and discards |n_bytes| on |remote_socket|. Returns true if at-least
106 // |n_bytes| were successfully discarded. (The actual number of discarded
107 // bytes is not known, as a pending datagram may be larger than our read
108 // buffer.)
DiscardFromSocket(size_t n_bytes_requested)109 [[nodiscard]] bool DiscardFromSocket(size_t n_bytes_requested) {
110 DynamicByteBuffer received_data(n_bytes_requested);
111 zx_status_t read_res;
112 size_t n_total_bytes_read = 0;
113 while (n_total_bytes_read < n_bytes_requested) {
114 size_t n_iter_bytes_read = 0;
115 read_res = remote_socket_.read(0,
116 received_data.mutable_data(),
117 received_data.size(),
118 &n_iter_bytes_read);
119 if (read_res != ZX_OK && read_res != ZX_ERR_SHOULD_WAIT) {
120 bt_log(ERROR,
121 "l2cap",
122 "Failure in zx_socket_read(): %s",
123 zx_status_get_string(read_res));
124 return false;
125 }
126 if (read_res == ZX_ERR_SHOULD_WAIT) {
127 EXPECT_EQ(n_bytes_requested, n_total_bytes_read);
128 return false;
129 } else {
130 n_total_bytes_read += n_iter_bytes_read;
131 }
132 }
133 return true;
134 }
135
136 protected:
137 static constexpr auto kGoodChar = 'a';
138 static constexpr auto kSpamChar = 'b';
channel()139 l2cap::testing::FakeChannel* channel() { return channel_.get(); }
dispatcher()140 async_dispatcher_t* dispatcher() { return loop_.dispatcher(); }
local_socket()141 zx::socket* local_socket() { return &local_socket_; }
local_socket_unowned()142 zx::unowned_socket local_socket_unowned() {
143 return zx::unowned_socket(local_socket_unowned_);
144 }
remote_socket()145 zx::socket* remote_socket() { return &remote_socket_; }
ConsumeLocalSocket()146 zx::socket ConsumeLocalSocket() { return std::move(local_socket_); }
CloseRemoteSocket()147 void CloseRemoteSocket() { remote_socket_.reset(); }
148 // Note: A call to RunLoopOnce() may cause multiple timer-based tasks
149 // to be dispatched. (When the timer expires, async_loop_run_once() dispatches
150 // all expired timer-based tasks.)
RunLoopOnce()151 void RunLoopOnce() { loop_.Run(zx::time::infinite(), /*once=*/true); }
RunLoopUntilIdle()152 void RunLoopUntilIdle() { loop_.RunUntilIdle(); }
ShutdownLoop()153 void ShutdownLoop() { loop_.Shutdown(); }
154
155 private:
156 std::unique_ptr<l2cap::testing::FakeChannel> channel_;
157 zx::socket local_socket_;
158 zx::socket remote_socket_;
159 zx::unowned_socket local_socket_unowned_;
160 // TODO(fxbug.dev/42150969): Move to FakeChannelTest, which wraps pw_async.
161 async::Loop loop_;
162 pw::async_fuchsia::FuchsiaDispatcher pw_dispatcher_;
163 };
164
165 class SocketChannelRelayLifetimeTest : public SocketChannelRelayTest {
166 public:
SocketChannelRelayLifetimeTest()167 SocketChannelRelayLifetimeTest()
168 : was_deactivation_callback_invoked_(false),
169 relay_(std::make_unique<RelayT>(
170 ConsumeLocalSocket(), channel()->GetWeakPtr(), [this]() {
171 was_deactivation_callback_invoked_ = true;
172 })) {}
173
174 protected:
was_deactivation_callback_invoked()175 bool was_deactivation_callback_invoked() {
176 return was_deactivation_callback_invoked_;
177 }
relay()178 RelayT* relay() {
179 PW_DCHECK(relay_);
180 return relay_.get();
181 }
DestroyRelay()182 void DestroyRelay() { relay_ = nullptr; }
183
184 private:
185 bool was_deactivation_callback_invoked_;
186 std::unique_ptr<RelayT> relay_;
187 };
188
TEST_F(SocketChannelRelayLifetimeTest,ActivateFailsIfGivenStoppedDispatcher)189 TEST_F(SocketChannelRelayLifetimeTest, ActivateFailsIfGivenStoppedDispatcher) {
190 ShutdownLoop();
191 EXPECT_FALSE(relay()->Activate());
192 }
193
TEST_F(SocketChannelRelayLifetimeTest,ActivateDoesNotInvokeDeactivationCallbackOnSuccess)194 TEST_F(SocketChannelRelayLifetimeTest,
195 ActivateDoesNotInvokeDeactivationCallbackOnSuccess) {
196 ASSERT_TRUE(relay()->Activate());
197 EXPECT_FALSE(was_deactivation_callback_invoked());
198 }
199
TEST_F(SocketChannelRelayLifetimeTest,ActivateDoesNotInvokeDeactivationCallbackOnFailure)200 TEST_F(SocketChannelRelayLifetimeTest,
201 ActivateDoesNotInvokeDeactivationCallbackOnFailure) {
202 ShutdownLoop();
203 ASSERT_FALSE(relay()->Activate());
204 EXPECT_FALSE(was_deactivation_callback_invoked());
205 }
206
TEST_F(SocketChannelRelayLifetimeTest,SocketIsClosedWhenRelayIsDestroyed)207 TEST_F(SocketChannelRelayLifetimeTest, SocketIsClosedWhenRelayIsDestroyed) {
208 const char data = kGoodChar;
209 ASSERT_EQ(ZX_OK, remote_socket()->write(0, &data, sizeof(data), nullptr));
210 DestroyRelay();
211 EXPECT_EQ(ZX_ERR_PEER_CLOSED,
212 remote_socket()->write(0, &data, sizeof(data), nullptr));
213 }
214
TEST_F(SocketChannelRelayLifetimeTest,RelayIsDeactivatedWhenDispatcherIsShutDown)215 TEST_F(SocketChannelRelayLifetimeTest,
216 RelayIsDeactivatedWhenDispatcherIsShutDown) {
217 ASSERT_TRUE(relay()->Activate());
218
219 ShutdownLoop();
220 EXPECT_TRUE(was_deactivation_callback_invoked());
221 }
222
TEST_F(SocketChannelRelayLifetimeTest,RelayActivationFailsIfChannelActivationFails)223 TEST_F(SocketChannelRelayLifetimeTest,
224 RelayActivationFailsIfChannelActivationFails) {
225 channel()->set_activate_fails(true);
226 EXPECT_FALSE(relay()->Activate());
227 }
228
TEST_F(SocketChannelRelayLifetimeTest,DestructionWithPendingSdusFromChannelDoesNotCrash)229 TEST_F(SocketChannelRelayLifetimeTest,
230 DestructionWithPendingSdusFromChannelDoesNotCrash) {
231 ASSERT_TRUE(relay()->Activate());
232 channel()->Receive(StaticByteBuffer('h', 'e', 'l', 'l', 'o'));
233 DestroyRelay();
234 RunLoopUntilIdle();
235 }
236
TEST_F(SocketChannelRelayLifetimeTest,RelayIsDeactivatedWhenChannelIsClosed)237 TEST_F(SocketChannelRelayLifetimeTest, RelayIsDeactivatedWhenChannelIsClosed) {
238 ASSERT_TRUE(relay()->Activate());
239
240 channel()->Close();
241 EXPECT_TRUE(was_deactivation_callback_invoked());
242 }
243
TEST_F(SocketChannelRelayLifetimeTest,RelayIsDeactivatedWhenRemoteSocketIsClosed)244 TEST_F(SocketChannelRelayLifetimeTest,
245 RelayIsDeactivatedWhenRemoteSocketIsClosed) {
246 ASSERT_TRUE(relay()->Activate());
247
248 CloseRemoteSocket();
249 RunLoopUntilIdle();
250 EXPECT_TRUE(was_deactivation_callback_invoked());
251 }
252
TEST_F(SocketChannelRelayLifetimeTest,RelayIsDeactivatedWhenRemoteSocketIsClosedEvenWithPendingSocketData)253 TEST_F(SocketChannelRelayLifetimeTest,
254 RelayIsDeactivatedWhenRemoteSocketIsClosedEvenWithPendingSocketData) {
255 ASSERT_TRUE(relay()->Activate());
256 ASSERT_TRUE(StuffSocket());
257
258 channel()->Receive(StaticByteBuffer('h', 'e', 'l', 'l', 'o'));
259 RunLoopUntilIdle();
260 ASSERT_FALSE(was_deactivation_callback_invoked());
261
262 CloseRemoteSocket();
263 RunLoopUntilIdle();
264 EXPECT_TRUE(was_deactivation_callback_invoked());
265 }
266
TEST_F(SocketChannelRelayLifetimeTest,OversizedDatagramDeactivatesRelay)267 TEST_F(SocketChannelRelayLifetimeTest, OversizedDatagramDeactivatesRelay) {
268 const size_t kMessageBufSize = channel()->max_tx_sdu_size() * 5;
269 DynamicByteBuffer large_message(kMessageBufSize);
270 large_message.Fill('a');
271 ASSERT_TRUE(relay()->Activate());
272
273 size_t n_bytes_written_to_socket = 0;
274 const auto write_res = remote_socket()->write(0,
275 large_message.data(),
276 large_message.size(),
277 &n_bytes_written_to_socket);
278 ASSERT_EQ(ZX_OK, write_res);
279 ASSERT_EQ(large_message.size(), n_bytes_written_to_socket);
280 RunLoopUntilIdle();
281
282 EXPECT_TRUE(was_deactivation_callback_invoked());
283 }
284
TEST_F(SocketChannelRelayLifetimeTest,SocketClosureAfterChannelClosureDoesNotHangOrCrash)285 TEST_F(SocketChannelRelayLifetimeTest,
286 SocketClosureAfterChannelClosureDoesNotHangOrCrash) {
287 ASSERT_TRUE(relay()->Activate());
288 channel()->Close();
289 ASSERT_TRUE(was_deactivation_callback_invoked());
290
291 CloseRemoteSocket();
292 RunLoopUntilIdle();
293 }
294
TEST_F(SocketChannelRelayLifetimeTest,ChannelClosureAfterSocketClosureDoesNotHangOrCrash)295 TEST_F(SocketChannelRelayLifetimeTest,
296 ChannelClosureAfterSocketClosureDoesNotHangOrCrash) {
297 ASSERT_TRUE(relay()->Activate());
298 CloseRemoteSocket();
299 RunLoopUntilIdle();
300
301 channel()->Close();
302 ASSERT_TRUE(was_deactivation_callback_invoked());
303 }
304
TEST_F(SocketChannelRelayLifetimeTest,DeactivationClosesSocket)305 TEST_F(SocketChannelRelayLifetimeTest, DeactivationClosesSocket) {
306 ASSERT_TRUE(relay()->Activate());
307 channel()->Close(); // Triggers relay deactivation.
308
309 const char data = kGoodChar;
310 EXPECT_EQ(ZX_ERR_PEER_CLOSED,
311 remote_socket()->write(0, &data, sizeof(data), nullptr));
312 }
313
314 class SocketChannelRelayDataPathTest : public SocketChannelRelayTest {
315 public:
SocketChannelRelayDataPathTest()316 SocketChannelRelayDataPathTest()
317 : relay_(ConsumeLocalSocket(),
318 channel()->GetWeakPtr(),
319 /*deactivation_cb=*/nullptr,
320 kDefaultSocketWriteQueueLimitFrames) {
321 channel()->SetSendCallback(
322 [&](auto data) { sent_to_channel_.push_back(std::move(data)); },
323 pw_dispatcher());
324 }
325
326 protected:
relay()327 RelayT* relay() { return &relay_; }
sent_to_channel()328 auto& sent_to_channel() { return sent_to_channel_; }
329
330 private:
331 RelayT relay_;
332 std::vector<ByteBufferPtr> sent_to_channel_;
333 };
334
335 // Fixture for tests which exercise the datapath from the controller.
336 class SocketChannelRelayRxTest : public SocketChannelRelayDataPathTest {
337 protected:
ReadDatagramFromSocket(const size_t dgram_len)338 DynamicByteBuffer ReadDatagramFromSocket(const size_t dgram_len) {
339 DynamicByteBuffer socket_read_buffer(dgram_len +
340 1); // +1 to detect trailing garbage.
341 size_t n_bytes_read = 0;
342 const auto read_res =
343 remote_socket()->read(0,
344 socket_read_buffer.mutable_data(),
345 socket_read_buffer.size(),
346 &n_bytes_read);
347 if (read_res != ZX_OK) {
348 bt_log(ERROR,
349 "l2cap",
350 "Failure in zx_socket_read(): %s",
351 zx_status_get_string(read_res));
352 return {};
353 }
354 return DynamicByteBuffer(BufferView(socket_read_buffer, n_bytes_read));
355 }
356 };
357
TEST_F(SocketChannelRelayRxTest,MessageFromChannelIsCopiedToSocketSynchronously)358 TEST_F(SocketChannelRelayRxTest,
359 MessageFromChannelIsCopiedToSocketSynchronously) {
360 const StaticByteBuffer kExpectedMessage('h', 'e', 'l', 'l', 'o');
361 ASSERT_TRUE(relay()->Activate());
362 channel()->Receive(kExpectedMessage);
363 // The data should be copied synchronously, so the async loop should not be
364 // run here.
365 EXPECT_TRUE(ContainersEqual(kExpectedMessage,
366 ReadDatagramFromSocket(kExpectedMessage.size())));
367 }
368
TEST_F(SocketChannelRelayRxTest,MultipleSdusFromChannelAreCopiedToSocketPreservingSduBoundaries)369 TEST_F(SocketChannelRelayRxTest,
370 MultipleSdusFromChannelAreCopiedToSocketPreservingSduBoundaries) {
371 const StaticByteBuffer kExpectedMessage1('h', 'e', 'l', 'l', 'o');
372 const StaticByteBuffer kExpectedMessage2('g', 'o', 'o', 'd', 'b', 'y', 'e');
373 ASSERT_TRUE(relay()->Activate());
374 channel()->Receive(kExpectedMessage1);
375 channel()->Receive(kExpectedMessage2);
376 RunLoopUntilIdle();
377
378 EXPECT_TRUE(ContainersEqual(
379 kExpectedMessage1, ReadDatagramFromSocket(kExpectedMessage1.size())));
380 EXPECT_TRUE(ContainersEqual(
381 kExpectedMessage2, ReadDatagramFromSocket(kExpectedMessage2.size())));
382 }
383
TEST_F(SocketChannelRelayRxTest,SduFromChannelIsCopiedToSocketWhenSocketUnblocks)384 TEST_F(SocketChannelRelayRxTest,
385 SduFromChannelIsCopiedToSocketWhenSocketUnblocks) {
386 size_t n_junk_bytes = StuffSocket();
387 ASSERT_TRUE(n_junk_bytes);
388
389 const StaticByteBuffer kExpectedMessage('h', 'e', 'l', 'l', 'o');
390 ASSERT_TRUE(relay()->Activate());
391 channel()->Receive(kExpectedMessage);
392 RunLoopUntilIdle();
393
394 ASSERT_TRUE(DiscardFromSocket(n_junk_bytes));
395 RunLoopUntilIdle();
396 EXPECT_TRUE(ContainersEqual(kExpectedMessage,
397 ReadDatagramFromSocket(kExpectedMessage.size())));
398 }
399
TEST_F(SocketChannelRelayRxTest,CanQueueAndWriteMultipleSDUs)400 TEST_F(SocketChannelRelayRxTest, CanQueueAndWriteMultipleSDUs) {
401 size_t n_junk_bytes = StuffSocket();
402 ASSERT_TRUE(n_junk_bytes);
403
404 const StaticByteBuffer kExpectedMessage1('h', 'e', 'l', 'l', 'o');
405 const StaticByteBuffer kExpectedMessage2('g', 'o', 'o', 'd', 'b', 'y', 'e');
406 ASSERT_TRUE(relay()->Activate());
407 channel()->Receive(kExpectedMessage1);
408 channel()->Receive(kExpectedMessage2);
409 RunLoopUntilIdle();
410
411 ASSERT_TRUE(DiscardFromSocket(n_junk_bytes));
412 // Run only one task. This verifies that the relay writes both pending SDUs in
413 // one shot, rather than re-arming the async::Wait for each SDU.
414 RunLoopOnce();
415
416 EXPECT_TRUE(ContainersEqual(
417 kExpectedMessage1, ReadDatagramFromSocket(kExpectedMessage1.size())));
418 EXPECT_TRUE(ContainersEqual(
419 kExpectedMessage2, ReadDatagramFromSocket(kExpectedMessage2.size())));
420 }
421
TEST_F(SocketChannelRelayRxTest,CanQueueAndIncrementallyWriteMultipleSDUs)422 TEST_F(SocketChannelRelayRxTest, CanQueueAndIncrementallyWriteMultipleSDUs) {
423 // Find the socket buffer size.
424 const size_t socket_buffer_size = StuffSocket();
425 ASSERT_TRUE(DiscardFromSocket(socket_buffer_size));
426
427 // Stuff the socket manually, rather than using StuffSocket(), so that we know
428 // exactly how much buffer space we free, as we read datagrams out of
429 // |remote_socket()|.
430 constexpr size_t kLargeSduSize = 1023;
431 zx_status_t write_res = ZX_ERR_INTERNAL;
432 DynamicByteBuffer spam_sdu(kLargeSduSize);
433 size_t n_junk_bytes = 0;
434 size_t n_junk_datagrams = 0;
435 spam_sdu.Fill('s');
436 do {
437 size_t n_iter_bytes_written = 0;
438 write_res = local_socket_unowned()->write(
439 0, spam_sdu.data(), spam_sdu.size(), &n_iter_bytes_written);
440 ASSERT_TRUE(write_res == ZX_OK || write_res == ZX_ERR_SHOULD_WAIT)
441 << "Failure in zx_socket_write: " << zx_status_get_string(write_res);
442 if (write_res == ZX_OK) {
443 ASSERT_EQ(spam_sdu.size(), n_iter_bytes_written);
444 n_junk_bytes += spam_sdu.size();
445 n_junk_datagrams += 1;
446 }
447 } while (write_res == ZX_OK);
448 ASSERT_NE(socket_buffer_size, n_junk_bytes)
449 << "Need non-zero free space in socket buffer.";
450
451 DynamicByteBuffer hello_sdu(kLargeSduSize);
452 DynamicByteBuffer goodbye_sdu(kLargeSduSize);
453 hello_sdu.Fill('h');
454 goodbye_sdu.Fill('g');
455 ASSERT_TRUE(relay()->Activate());
456 channel()->Receive(hello_sdu);
457 channel()->Receive(goodbye_sdu);
458 RunLoopUntilIdle();
459
460 // Free up space for just the first SDU.
461 ASSERT_TRUE(
462 ContainersEqual(spam_sdu, ReadDatagramFromSocket(spam_sdu.size())));
463 n_junk_datagrams -= 1;
464 RunLoopUntilIdle();
465
466 // Free up space for just the second SDU.
467 ASSERT_TRUE(
468 ContainersEqual(spam_sdu, ReadDatagramFromSocket(spam_sdu.size())));
469 n_junk_datagrams -= 1;
470 RunLoopUntilIdle();
471
472 // Discard spam.
473 while (n_junk_datagrams) {
474 ASSERT_TRUE(
475 ContainersEqual(spam_sdu, ReadDatagramFromSocket(spam_sdu.size())));
476 n_junk_datagrams -= 1;
477 }
478
479 // Read out our expected datagrams, verifying that boundaries are preserved.
480 EXPECT_TRUE(
481 ContainersEqual(hello_sdu, ReadDatagramFromSocket(hello_sdu.size())));
482 EXPECT_TRUE(
483 ContainersEqual(goodbye_sdu, ReadDatagramFromSocket(goodbye_sdu.size())));
484 EXPECT_EQ(0u, ReadDatagramFromSocket(1u).size())
485 << "Found unexpected datagram";
486 }
487
TEST_F(SocketChannelRelayRxTest,ZeroByteSDUsDropped)488 TEST_F(SocketChannelRelayRxTest, ZeroByteSDUsDropped) {
489 const StaticByteBuffer kMessage1('h', 'e', 'l', 'l', 'o');
490 DynamicByteBuffer kMessageZero(0);
491 const StaticByteBuffer kMessage3('f', 'u', 'c', 'h', 's', 'i', 'a');
492
493 ASSERT_TRUE(relay()->Activate());
494 channel()->Receive(kMessageZero);
495 channel()->Receive(kMessage1);
496 channel()->Receive(kMessageZero);
497 channel()->Receive(kMessage3);
498 channel()->Receive(kMessageZero);
499 RunLoopUntilIdle();
500
501 ASSERT_TRUE(
502 ContainersEqual(kMessage1, ReadDatagramFromSocket(kMessage1.size())));
503 ASSERT_TRUE(
504 ContainersEqual(kMessage3, ReadDatagramFromSocket(kMessage3.size())));
505
506 EXPECT_EQ(0u, ReadDatagramFromSocket(1u).size())
507 << "Found unexpected datagram";
508 }
509
TEST_F(SocketChannelRelayRxTest,OldestSDUIsDroppedOnOverflow)510 TEST_F(SocketChannelRelayRxTest, OldestSDUIsDroppedOnOverflow) {
511 size_t n_junk_bytes = StuffSocket();
512 ASSERT_TRUE(n_junk_bytes);
513
514 const StaticByteBuffer kSentMessage1(1);
515 const StaticByteBuffer kSentMessage2(2);
516 const StaticByteBuffer kSentMessage3(3);
517 ASSERT_TRUE(relay()->Activate());
518 channel()->Receive(kSentMessage1);
519 channel()->Receive(kSentMessage2);
520 channel()->Receive(kSentMessage3);
521 RunLoopUntilIdle();
522
523 ASSERT_TRUE(DiscardFromSocket(n_junk_bytes));
524 RunLoopUntilIdle();
525
526 EXPECT_TRUE(ContainersEqual(kSentMessage2,
527 ReadDatagramFromSocket(kSentMessage2.size())));
528 EXPECT_TRUE(ContainersEqual(kSentMessage3,
529 ReadDatagramFromSocket(kSentMessage3.size())));
530 }
531
TEST_F(SocketChannelRelayRxTest,SdusReceivedBeforeChannelActivationAreCopiedToSocket)532 TEST_F(SocketChannelRelayRxTest,
533 SdusReceivedBeforeChannelActivationAreCopiedToSocket) {
534 const StaticByteBuffer kExpectedMessage1('h', 'e', 'l', 'l', 'o');
535 const StaticByteBuffer kExpectedMessage2('g', 'o', 'o', 'd', 'b', 'y', 'e');
536 channel()->Receive(kExpectedMessage1);
537 channel()->Receive(kExpectedMessage2);
538 ASSERT_TRUE(relay()->Activate());
539 // Note: we omit RunLoopOnce()/RunLoopUntilIdle(), as Channel activation
540 // delivers the messages synchronously.
541
542 EXPECT_TRUE(ContainersEqual(
543 kExpectedMessage1, ReadDatagramFromSocket(kExpectedMessage1.size())));
544 EXPECT_TRUE(ContainersEqual(
545 kExpectedMessage2, ReadDatagramFromSocket(kExpectedMessage2.size())));
546 }
547
TEST_F(SocketChannelRelayRxTest,SdusPendingAtChannelClosureAreCopiedToSocket)548 TEST_F(SocketChannelRelayRxTest, SdusPendingAtChannelClosureAreCopiedToSocket) {
549 ASSERT_TRUE(StuffSocket());
550 ASSERT_TRUE(relay()->Activate());
551
552 const StaticByteBuffer kExpectedMessage1('h');
553 const StaticByteBuffer kExpectedMessage2('i');
554 channel()->Receive(kExpectedMessage1);
555 channel()->Receive(kExpectedMessage2);
556 RunLoopUntilIdle();
557
558 // Discard two datagrams from socket, to make room for our SDUs to be copied
559 // over.
560 ASSERT_NE(0u, ReadDatagramFromSocket(1u).size());
561 ASSERT_NE(0u, ReadDatagramFromSocket(1u).size());
562 channel()->Close();
563
564 // Read past all of the spam from StuffSocket().
565 DynamicByteBuffer dgram;
566 do {
567 dgram = ReadDatagramFromSocket(1u);
568 } while (dgram.size() && dgram[0] == kSpamChar);
569
570 // First non-spam message should be kExpectedMessage1, and second should be
571 // kExpectedMessage2.
572 EXPECT_TRUE(ContainersEqual(kExpectedMessage1, dgram));
573 EXPECT_TRUE(ContainersEqual(kExpectedMessage2, ReadDatagramFromSocket(1u)));
574 }
575
TEST_F(SocketChannelRelayRxTest,ReceivingFromChannelBetweenSocketCloseAndCloseWaitTriggerDoesNotCrash)576 TEST_F(SocketChannelRelayRxTest,
577 ReceivingFromChannelBetweenSocketCloseAndCloseWaitTriggerDoesNotCrash) {
578 // Note: we call Channel::Receive() first, to force FakeChannel to deliver the
579 // SDU synchronously to the SocketChannelRelay. Asynchronous delivery could
580 // compromise the test's validity, since that would allow OnSocketClosed() to
581 // be invoked before OnChannelDataReceived().
582 channel()->Receive(StaticByteBuffer(kGoodChar));
583 CloseRemoteSocket();
584 ASSERT_TRUE(relay()->Activate());
585 }
586
TEST_F(SocketChannelRelayRxTest,SocketCloseBetweenReceivingFromChannelAndSocketWritabilityDoesNotCrashOrHang)587 TEST_F(
588 SocketChannelRelayRxTest,
589 SocketCloseBetweenReceivingFromChannelAndSocketWritabilityDoesNotCrashOrHang) {
590 ASSERT_TRUE(relay()->Activate());
591
592 size_t n_junk_bytes = StuffSocket();
593 ASSERT_TRUE(n_junk_bytes);
594 channel()->Receive(StaticByteBuffer(kGoodChar));
595 RunLoopUntilIdle();
596
597 ASSERT_TRUE(DiscardFromSocket(n_junk_bytes));
598 CloseRemoteSocket();
599 RunLoopUntilIdle();
600 }
601
TEST_F(SocketChannelRelayRxTest,NoDataFromChannelIsWrittenToSocketAfterDeactivation)602 TEST_F(SocketChannelRelayRxTest,
603 NoDataFromChannelIsWrittenToSocketAfterDeactivation) {
604 ASSERT_TRUE(relay()->Activate());
605
606 size_t n_junk_bytes = StuffSocket();
607 ASSERT_TRUE(n_junk_bytes);
608
609 channel()->Receive(StaticByteBuffer('h', 'e', 'l', 'l', 'o'));
610 RunLoopUntilIdle();
611
612 channel()->Close(); // Triggers relay deactivation.
613 ASSERT_TRUE(DiscardFromSocket(n_junk_bytes));
614 RunLoopUntilIdle();
615
616 zx_info_socket_t info = {};
617 info.rx_buf_available = std::numeric_limits<size_t>::max();
618 const auto status = remote_socket()->get_info(ZX_INFO_SOCKET,
619 &info,
620 sizeof(info),
621 /*actual_count=*/nullptr,
622 /*avail_count=*/nullptr);
623 EXPECT_EQ(ZX_OK, status);
624 EXPECT_EQ(0u, info.rx_buf_available);
625 }
626
627 // Alias for the fixture for tests which exercise the datapath to the
628 // controller.
629 using SocketChannelRelayTxTest = SocketChannelRelayDataPathTest;
630
TEST_F(SocketChannelRelayTxTest,SduFromSocketIsCopiedToChannel)631 TEST_F(SocketChannelRelayTxTest, SduFromSocketIsCopiedToChannel) {
632 const StaticByteBuffer kExpectedMessage('h', 'e', 'l', 'l', 'o');
633 ASSERT_TRUE(relay()->Activate());
634
635 size_t n_bytes_written = 0;
636 const auto write_res = remote_socket()->write(
637 0, kExpectedMessage.data(), kExpectedMessage.size(), &n_bytes_written);
638 ASSERT_EQ(ZX_OK, write_res);
639 ASSERT_EQ(kExpectedMessage.size(), n_bytes_written);
640 RunLoopUntilIdle();
641
642 const auto& sdus = sent_to_channel();
643 ASSERT_FALSE(sdus.empty());
644 EXPECT_EQ(1u, sdus.size());
645 ASSERT_TRUE(sdus[0]);
646 EXPECT_EQ(kExpectedMessage.size(), sdus[0]->size());
647 EXPECT_TRUE(ContainersEqual(kExpectedMessage, *sdus[0]));
648 }
649
TEST_F(SocketChannelRelayTxTest,MultipleSdusFromSocketAreCopiedToChannel)650 TEST_F(SocketChannelRelayTxTest, MultipleSdusFromSocketAreCopiedToChannel) {
651 const StaticByteBuffer kExpectedMessage('h', 'e', 'l', 'l', 'o');
652 const size_t kNumMessages = 3;
653 ASSERT_TRUE(relay()->Activate());
654
655 for (size_t i = 0; i < kNumMessages; ++i) {
656 size_t n_bytes_written = 0;
657 const auto write_res = remote_socket()->write(
658 0, kExpectedMessage.data(), kExpectedMessage.size(), &n_bytes_written);
659 ASSERT_EQ(ZX_OK, write_res);
660 ASSERT_EQ(kExpectedMessage.size(), n_bytes_written);
661 RunLoopUntilIdle();
662 }
663
664 const auto& sdus = sent_to_channel();
665 ASSERT_FALSE(sdus.empty());
666 ASSERT_EQ(3U, sdus.size());
667 ASSERT_TRUE(sdus[0]);
668 ASSERT_TRUE(sdus[1]);
669 ASSERT_TRUE(sdus[2]);
670 EXPECT_TRUE(ContainersEqual(kExpectedMessage, *sdus[0]));
671 EXPECT_TRUE(ContainersEqual(kExpectedMessage, *sdus[1]));
672 EXPECT_TRUE(ContainersEqual(kExpectedMessage, *sdus[2]));
673 }
674
TEST_F(SocketChannelRelayTxTest,MultipleSdusAreCopiedToChannelInOneRelayTask)675 TEST_F(SocketChannelRelayTxTest, MultipleSdusAreCopiedToChannelInOneRelayTask) {
676 const StaticByteBuffer kExpectedMessage('h', 'e', 'l', 'l', 'o');
677 const size_t kNumMessages = 3;
678 ASSERT_TRUE(relay()->Activate());
679
680 for (size_t i = 0; i < kNumMessages; ++i) {
681 size_t n_bytes_written = 0;
682 const auto write_res = remote_socket()->write(
683 0, kExpectedMessage.data(), kExpectedMessage.size(), &n_bytes_written);
684 ASSERT_EQ(ZX_OK, write_res);
685 ASSERT_EQ(kExpectedMessage.size(), n_bytes_written);
686 }
687
688 RunLoopOnce(); // Runs SocketChannelRelay::OnSocketReadable().
689 RunLoopOnce(); // Runs all tasks queued by FakeChannel::Send().
690
691 const auto& sdus = sent_to_channel();
692 ASSERT_FALSE(sdus.empty());
693 ASSERT_EQ(3U, sdus.size());
694 ASSERT_TRUE(sdus[0]);
695 ASSERT_TRUE(sdus[1]);
696 ASSERT_TRUE(sdus[2]);
697 EXPECT_TRUE(ContainersEqual(kExpectedMessage, *sdus[0]));
698 EXPECT_TRUE(ContainersEqual(kExpectedMessage, *sdus[1]));
699 EXPECT_TRUE(ContainersEqual(kExpectedMessage, *sdus[2]));
700 }
701
TEST_F(SocketChannelRelayTxTest,OversizedSduIsDropped)702 TEST_F(SocketChannelRelayTxTest, OversizedSduIsDropped) {
703 const size_t kMessageBufSize = channel()->max_tx_sdu_size() * 5;
704 DynamicByteBuffer large_message(kMessageBufSize);
705 large_message.Fill(kGoodChar);
706 ASSERT_TRUE(relay()->Activate());
707
708 size_t n_bytes_written_to_socket = 0;
709 const auto write_res = remote_socket()->write(0,
710 large_message.data(),
711 large_message.size(),
712 &n_bytes_written_to_socket);
713 ASSERT_EQ(ZX_OK, write_res);
714 ASSERT_EQ(large_message.size(), n_bytes_written_to_socket);
715 RunLoopUntilIdle();
716
717 ASSERT_TRUE(sent_to_channel().empty());
718 }
719
TEST_F(SocketChannelRelayTxTest,ValidSduAfterOversizedSduIsIgnored)720 TEST_F(SocketChannelRelayTxTest, ValidSduAfterOversizedSduIsIgnored) {
721 const StaticByteBuffer kSentMsg('h', 'e', 'l', 'l', 'o');
722 ASSERT_TRUE(relay()->Activate());
723
724 {
725 DynamicByteBuffer dropped_msg(channel()->max_tx_sdu_size() + 1);
726 size_t n_bytes_written = 0;
727 zx_status_t write_res = ZX_ERR_INTERNAL;
728 dropped_msg.Fill(kGoodChar);
729 write_res = remote_socket()->write(
730 0, dropped_msg.data(), dropped_msg.size(), &n_bytes_written);
731 ASSERT_EQ(ZX_OK, write_res);
732 ASSERT_EQ(dropped_msg.size(), n_bytes_written);
733 }
734
735 {
736 size_t n_bytes_written = 0;
737 zx_status_t write_res = ZX_ERR_INTERNAL;
738 write_res = remote_socket()->write(
739 0, kSentMsg.data(), kSentMsg.size(), &n_bytes_written);
740 ASSERT_EQ(ZX_OK, write_res);
741 ASSERT_EQ(kSentMsg.size(), n_bytes_written);
742 }
743
744 RunLoopUntilIdle();
745 EXPECT_TRUE(sent_to_channel().empty());
746 }
747
TEST_F(SocketChannelRelayTxTest,NewSocketDataAfterChannelClosureIsNotSentToChannel)748 TEST_F(SocketChannelRelayTxTest,
749 NewSocketDataAfterChannelClosureIsNotSentToChannel) {
750 ASSERT_TRUE(relay()->Activate());
751 channel()->Close();
752
753 const char data = kGoodChar;
754 const auto write_res =
755 remote_socket()->write(0, &data, sizeof(data), /*actual=*/nullptr);
756 ASSERT_TRUE(write_res == ZX_OK || write_res == ZX_ERR_PEER_CLOSED)
757 << ": " << zx_status_get_string(write_res);
758 RunLoopUntilIdle();
759 EXPECT_TRUE(sent_to_channel().empty());
760 }
761
TEST_F(SocketChannelRelayRxTest,DrainWriteQueueWhileSocketWritableWaitIsPending)762 TEST_F(SocketChannelRelayRxTest,
763 DrainWriteQueueWhileSocketWritableWaitIsPending) {
764 ASSERT_EQ(kDefaultSocketWriteQueueLimitFrames, 2u);
765 const StaticByteBuffer kSentMessage0(0);
766 const StaticByteBuffer kSentMessage1(1, 1, 1);
767 const StaticByteBuffer kSentMessage2(2);
768 const StaticByteBuffer kSentMessage3(3);
769
770 // Make the first 2 datagrams 1 byte each so that we can discard exactly 2
771 // bytes after stuffing the socket.
772 size_t n_bytes_written = 0;
773 zx_status_t write_res = local_socket_unowned()->write(
774 0, kSentMessage0.data(), kSentMessage0.size(), &n_bytes_written);
775 ASSERT_EQ(write_res, ZX_OK);
776 ASSERT_EQ(n_bytes_written, 1u);
777 write_res = local_socket_unowned()->write(
778 0, kSentMessage0.data(), kSentMessage0.size(), &n_bytes_written);
779 ASSERT_EQ(write_res, ZX_OK);
780 ASSERT_EQ(n_bytes_written, 1u);
781
782 size_t n_junk_bytes = StuffSocket();
783 ASSERT_TRUE(n_junk_bytes);
784
785 ASSERT_TRUE(relay()->Activate());
786
787 // Drain enough space for kSentMessage2 and kSentMessage3, but not
788 // kSentMessage1!
789 ASSERT_TRUE(DiscardFromSocket(2 * kSentMessage0.size()));
790
791 // The kSentMessage1 is too big to write to the almost-stuffed socket. The
792 // packet will be queued, and the "socket writable" signal wait will start.
793 channel()->Receive(kSentMessage1);
794 // The second 1-byte packet that will fit into the socket is also queued.
795 channel()->Receive(kSentMessage2);
796 // When the third 1-byte packet is queued, kSentMessage1 will be dropped from
797 // the queue, allowing kSentMessage2 and kSendMessage3 to be written to the
798 // socket. The queue will be emptied.
799 channel()->Receive(kSentMessage3);
800
801 // Allow any signals to be processed.
802 RunLoopUntilIdle();
803
804 // Verify that kSentMessage2 and kSentMessage3 were actually written to the
805 // socket.
806 ASSERT_TRUE(DiscardFromSocket(n_junk_bytes));
807 RunLoopUntilIdle();
808 EXPECT_TRUE(ContainersEqual(kSentMessage2,
809 ReadDatagramFromSocket(kSentMessage2.size())));
810 EXPECT_TRUE(ContainersEqual(kSentMessage3,
811 ReadDatagramFromSocket(kSentMessage3.size())));
812 }
813
814 } // namespace
815 } // namespace bt::socket
816