• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 <cstddef>
17 #include <span>
18 #include <utility>
19 
20 #include "pw_containers/intrusive_list.h"
21 #include "pw_rpc/internal/call.h"
22 #include "pw_rpc/internal/channel.h"
23 #include "pw_rpc/internal/method.h"
24 #include "pw_rpc/service.h"
25 #include "pw_status/status.h"
26 
27 namespace pw::rpc {
28 
29 class Server;
30 
31 namespace internal {
32 
33 class Packet;
34 
35 // Internal ServerWriter base class. ServerWriters are used to stream responses.
36 // Implementations must provide a derived class that provides the interface for
37 // sending responses.
38 class BaseServerWriter : public IntrusiveList<BaseServerWriter>::Item {
39  public:
40   BaseServerWriter(ServerCall& call);
41 
42   BaseServerWriter(const BaseServerWriter&) = delete;
43 
BaseServerWriter(BaseServerWriter && other)44   BaseServerWriter(BaseServerWriter&& other) : state_(kClosed) {
45     *this = std::move(other);
46   }
47 
~BaseServerWriter()48   ~BaseServerWriter() { Finish(); }
49 
50   BaseServerWriter& operator=(const BaseServerWriter&) = delete;
51 
52   BaseServerWriter& operator=(BaseServerWriter&& other);
53 
54   // True if the ServerWriter is active and ready to send responses.
open()55   bool open() const { return state_ == kOpen; }
56 
channel_id()57   uint32_t channel_id() const { return call_.channel().id(); }
service_id()58   uint32_t service_id() const { return call_.service().id(); }
59   uint32_t method_id() const;
60 
61   // Closes the ServerWriter, if it is open.
62   Status Finish(Status status = OkStatus());
63 
64  protected:
BaseServerWriter()65   constexpr BaseServerWriter() : state_{kClosed} {}
66 
method()67   const Method& method() const { return call_.method(); }
68 
channel()69   const Channel& channel() const { return call_.channel(); }
70 
buffer()71   constexpr const Channel::OutputBuffer& buffer() const { return response_; }
72 
73   // Acquires a buffer into which to write a payload. The BaseServerWriter MUST
74   // be open when this is called!
75   std::span<std::byte> AcquirePayloadBuffer();
76 
77   // Releases the buffer, sending a packet with the specified payload. The
78   // BaseServerWriter MUST be open when this is called!
79   Status ReleasePayloadBuffer(std::span<const std::byte> payload);
80 
81   // Releases the buffer without sending a packet.
82   Status ReleasePayloadBuffer();
83 
84  private:
85   friend class rpc::Server;
86 
87   void Close();
88 
89   Packet ResponsePacket(std::span<const std::byte> payload = {}) const;
90 
91   ServerCall call_;
92   Channel::OutputBuffer response_;
93   enum { kClosed, kOpen } state_;
94 };
95 
96 }  // namespace internal
97 }  // namespace pw::rpc
98