• 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 #pragma once
15 
16 #include <cstdint>
17 #include <optional>
18 
19 #include "pw_async2/dispatcher.h"
20 #include "pw_async2/poll.h"
21 #include "pw_channel/channel.h"
22 #include "pw_multibuf/allocator.h"
23 #include "pw_multibuf/multibuf.h"
24 
25 namespace pw::channel {
26 
27 /// @defgroup pw_channel_loopback
28 /// @{
29 
30 // Channel implementation which will read its own writes.
31 template <DataType kType>
32 class LoopbackChannel;
33 
34 /// Alias for a loopback channel that sends and receives datagrams.
35 using LoopbackDatagramChannel = LoopbackChannel<DataType::kDatagram>;
36 
37 /// Alias for a loopback channel that sends and receives bytes.
38 using LoopbackByteChannel = LoopbackChannel<DataType::kByte>;
39 
40 /// @}
41 
42 template <>
43 class LoopbackChannel<DataType::kDatagram>
44     : public ReliableDatagramReaderWriter {
45  public:
LoopbackChannel(multibuf::MultiBufAllocator & write_allocator)46   LoopbackChannel(multibuf::MultiBufAllocator& write_allocator)
47       : write_allocator_(&write_allocator) {}
48   LoopbackChannel(const LoopbackChannel&) = delete;
49   LoopbackChannel& operator=(const LoopbackChannel&) = delete;
50 
51   LoopbackChannel(LoopbackChannel&&) = default;
52   LoopbackChannel& operator=(LoopbackChannel&&) = default;
53 
54  private:
55   async2::Poll<Result<multibuf::MultiBuf>> DoPendRead(
56       async2::Context& cx) override;
57 
58   async2::Poll<Status> DoPendReadyToWrite(async2::Context& cx) final;
59 
DoGetWriteAllocator()60   multibuf::MultiBufAllocator& DoGetWriteAllocator() final {
61     return *write_allocator_;
62   }
63 
64   Result<channel::WriteToken> DoWrite(multibuf::MultiBuf&& data) final;
65 
66   async2::Poll<Result<channel::WriteToken>> DoPendFlush(async2::Context&) final;
67 
68   async2::Poll<Status> DoPendClose(async2::Context&) final;
69 
70   multibuf::MultiBufAllocator* write_allocator_;
71   std::optional<multibuf::MultiBuf> queue_;
72   uint32_t write_token_;
73   async2::Waker waker_;
74 };
75 
76 template <>
77 class LoopbackChannel<DataType::kByte> : public ReliableByteReaderWriter {
78  public:
LoopbackChannel(multibuf::MultiBufAllocator & write_allocator)79   LoopbackChannel(multibuf::MultiBufAllocator& write_allocator)
80       : write_allocator_(&write_allocator) {}
81   LoopbackChannel(const LoopbackChannel&) = delete;
82   LoopbackChannel& operator=(const LoopbackChannel&) = delete;
83 
84   LoopbackChannel(LoopbackChannel&&) = default;
85   LoopbackChannel& operator=(LoopbackChannel&&) = default;
86 
87  private:
88   async2::Poll<Result<multibuf::MultiBuf>> DoPendRead(
89       async2::Context& cx) override;
90 
DoPendReadyToWrite(async2::Context &)91   async2::Poll<Status> DoPendReadyToWrite(async2::Context&) final {
92     return async2::Ready(OkStatus());
93   }
94 
DoGetWriteAllocator()95   multibuf::MultiBufAllocator& DoGetWriteAllocator() final {
96     return *write_allocator_;
97   }
98 
99   Result<channel::WriteToken> DoWrite(multibuf::MultiBuf&& data) final;
100 
101   async2::Poll<Result<channel::WriteToken>> DoPendFlush(async2::Context&) final;
102 
103   async2::Poll<Status> DoPendClose(async2::Context&) final;
104 
105   multibuf::MultiBufAllocator* write_allocator_;
106   multibuf::MultiBuf queue_;
107   uint32_t write_token_;
108   async2::Waker read_waker_;
109 };
110 
111 }  // namespace pw::channel
112