• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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 // This file defines the ServerReaderWriter, ServerReader, and ServerWriter
16 // classes for the raw RPC interface. These classes are used for bidirectional,
17 // client, and server streaming RPCs.
18 #pragma once
19 
20 #include "pw_bytes/span.h"
21 #include "pw_rpc/channel.h"
22 #include "pw_rpc/internal/method_info.h"
23 #include "pw_rpc/internal/method_lookup.h"
24 #include "pw_rpc/internal/server_call.h"
25 #include "pw_rpc/server.h"
26 #include "pw_rpc/writer.h"
27 
28 namespace pw::rpc {
29 namespace internal {
30 
31 // Forward declarations for internal classes needed in friend statements.
32 class RawMethod;
33 
34 namespace test {
35 
36 template <typename, typename, uint32_t>
37 class InvocationContext;
38 
39 }  // namespace test
40 }  // namespace internal
41 
42 class RawServerReader;
43 class RawServerWriter;
44 
45 // The RawServerReaderWriter is used to send and receive messages in a raw
46 // bidirectional streaming RPC.
47 class RawServerReaderWriter : private internal::ServerCall {
48  public:
49   constexpr RawServerReaderWriter() = default;
50 
51   RawServerReaderWriter(RawServerReaderWriter&&) = default;
52   RawServerReaderWriter& operator=(RawServerReaderWriter&&) = default;
53 
54   // Creates a RawServerReaderWriter that is ready to send responses for a
55   // particular RPC. This can be used for testing or to send responses to an RPC
56   // that has not been started by a client.
57   template <auto kMethod, typename ServiceImpl>
Open(Server & server,uint32_t channel_id,ServiceImpl & service)58   [[nodiscard]] static RawServerReaderWriter Open(Server& server,
59                                                   uint32_t channel_id,
60                                                   ServiceImpl& service)
61       PW_LOCKS_EXCLUDED(internal::rpc_lock()) {
62     return server.OpenCall<RawServerReaderWriter,
63                            kMethod,
64                            MethodType::kBidirectionalStreaming>(
65         channel_id,
66         service,
67         internal::MethodLookup::GetRawMethod<
68             ServiceImpl,
69             internal::MethodInfo<kMethod>::kMethodId>());
70   }
71 
72   using internal::Call::active;
73   using internal::Call::channel_id;
74 
75   // Functions for setting the callbacks.
76   using internal::Call::set_on_error;
77   using internal::Call::set_on_next;
78   using internal::ServerCall::set_on_client_stream_end;
79 
80   // Sends a response packet with the given raw payload.
81   using internal::Call::Write;
82 
83   Status Finish(Status status = OkStatus()) {
84     return CloseAndSendResponse(status);
85   }
86 
87   // Allow use as a generic RPC Writer.
88   using internal::Call::operator Writer&;
89   using internal::Call::operator const Writer&;
90 
91  protected:
RawServerReaderWriter(const internal::LockedCallContext & context,MethodType type)92   RawServerReaderWriter(const internal::LockedCallContext& context,
93                         MethodType type)
94       PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock())
95       : internal::ServerCall(
96             context,
97             internal::CallProperties(
98                 type, internal::kServerCall, internal::kRawProto)) {}
99 
100   using internal::Call::CloseAndSendResponse;
101 
102  private:
103   friend class internal::RawMethod;  // Needed to construct
104   friend class Server;
105 
106   template <typename, typename, uint32_t>
107   friend class internal::test::InvocationContext;
108 
109   // Private constructor for test use
RawServerReaderWriter(const internal::LockedCallContext & context)110   RawServerReaderWriter(const internal::LockedCallContext& context)
111       : RawServerReaderWriter(context, MethodType::kBidirectionalStreaming) {}
112 };
113 
114 // The RawServerReader is used to receive messages and send a response in a
115 // raw client streaming RPC.
116 class RawServerReader : private RawServerReaderWriter {
117  public:
118   // Creates a RawServerReader that is ready to send a response to a particular
119   // RPC. This can be used for testing or to finish an RPC that has not been
120   // started by the client.
121   template <auto kMethod, typename ServiceImpl>
Open(Server & server,uint32_t channel_id,ServiceImpl & service)122   [[nodiscard]] static RawServerReader Open(Server& server,
123                                             uint32_t channel_id,
124                                             ServiceImpl& service)
125       PW_LOCKS_EXCLUDED(internal::rpc_lock()) {
126     return server
127         .OpenCall<RawServerReader, kMethod, MethodType::kClientStreaming>(
128             channel_id,
129             service,
130             internal::MethodLookup::GetRawMethod<
131                 ServiceImpl,
132                 internal::MethodInfo<kMethod>::kMethodId>());
133   }
134 
135   constexpr RawServerReader() = default;
136 
137   RawServerReader(RawServerReader&&) = default;
138   RawServerReader& operator=(RawServerReader&&) = default;
139 
140   using RawServerReaderWriter::active;
141   using RawServerReaderWriter::channel_id;
142 
143   using RawServerReaderWriter::set_on_client_stream_end;
144   using RawServerReaderWriter::set_on_error;
145   using RawServerReaderWriter::set_on_next;
146 
147   Status Finish(ConstByteSpan response, Status status = OkStatus()) {
148     return CloseAndSendResponse(response, status);
149   }
150 
151  private:
152   friend class internal::RawMethod;  // Needed for conversions from ReaderWriter
153   friend class Server;
154 
155   template <typename, typename, uint32_t>
156   friend class internal::test::InvocationContext;
157 
158   RawServerReader(const internal::LockedCallContext& context)
PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock ())159       PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock())
160       : RawServerReaderWriter(context, MethodType::kClientStreaming) {}
161 };
162 
163 // The RawServerWriter is used to send responses in a raw server streaming RPC.
164 class RawServerWriter : private RawServerReaderWriter {
165  public:
166   // Creates a RawServerWriter that is ready to send responses for a particular
167   // RPC. This can be used for testing or to send responses to an RPC that has
168   // not been started by a client.
169   template <auto kMethod, typename ServiceImpl>
Open(Server & server,uint32_t channel_id,ServiceImpl & service)170   [[nodiscard]] static RawServerWriter Open(Server& server,
171                                             uint32_t channel_id,
172                                             ServiceImpl& service)
173       PW_LOCKS_EXCLUDED(internal::rpc_lock()) {
174     return server
175         .OpenCall<RawServerWriter, kMethod, MethodType::kServerStreaming>(
176             channel_id,
177             service,
178             internal::MethodLookup::GetRawMethod<
179                 ServiceImpl,
180                 internal::MethodInfo<kMethod>::kMethodId>());
181   }
182 
183   constexpr RawServerWriter() = default;
184 
185   RawServerWriter(RawServerWriter&&) = default;
186   RawServerWriter& operator=(RawServerWriter&&) = default;
187 
188   using RawServerReaderWriter::active;
189   using RawServerReaderWriter::channel_id;
190 
191   using RawServerReaderWriter::set_on_error;
192 
193   using RawServerReaderWriter::Finish;
194   using RawServerReaderWriter::Write;
195 
196   // Allow use as a generic RPC Writer.
197   using internal::Call::operator Writer&;
198   using internal::Call::operator const Writer&;
199 
200  private:
201   friend class internal::RawMethod;
202   friend class Server;
203 
204   template <typename, typename, uint32_t>
205   friend class internal::test::InvocationContext;
206 
207   RawServerWriter(const internal::LockedCallContext& context)
PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock ())208       PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock())
209       : RawServerReaderWriter(context, MethodType::kServerStreaming) {}
210 };
211 
212 // The RawUnaryResponder is used to send a response in a raw unary RPC.
213 class RawUnaryResponder : private RawServerReaderWriter {
214  public:
215   // Creates a RawUnaryResponder that is ready to send responses for a
216   // particular RPC. This can be used for testing or to send responses to an RPC
217   // that has not been started by a client.
218   template <auto kMethod, typename ServiceImpl>
Open(Server & server,uint32_t channel_id,ServiceImpl & service)219   [[nodiscard]] static RawUnaryResponder Open(Server& server,
220                                               uint32_t channel_id,
221                                               ServiceImpl& service)
222       PW_LOCKS_EXCLUDED(internal::rpc_lock()) {
223     return server.OpenCall<RawUnaryResponder, kMethod, MethodType::kUnary>(
224         channel_id,
225         service,
226         internal::MethodLookup::GetRawMethod<
227             ServiceImpl,
228             internal::MethodInfo<kMethod>::kMethodId>());
229   }
230 
231   constexpr RawUnaryResponder() = default;
232 
233   RawUnaryResponder(RawUnaryResponder&&) = default;
234   RawUnaryResponder& operator=(RawUnaryResponder&&) = default;
235 
236   using RawServerReaderWriter::active;
237   using RawServerReaderWriter::channel_id;
238 
239   using RawServerReaderWriter::set_on_error;
240 
241   Status Finish(ConstByteSpan response, Status status = OkStatus()) {
242     return CloseAndSendResponse(response, status);
243   }
244 
245  private:
246   friend class internal::RawMethod;
247   friend class Server;
248 
249   template <typename, typename, uint32_t>
250   friend class internal::test::InvocationContext;
251 
252   RawUnaryResponder(const internal::LockedCallContext& context)
PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock ())253       PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock())
254       : RawServerReaderWriter(context, MethodType::kUnary) {}
255 };
256 
257 }  // namespace pw::rpc
258