blob: 7761b3a5cf779edfe5e6f8d0978e008fadf3fa33 [file] [log] [blame]
Wyatt Heplercb9d9572020-06-01 11:25:58 -07001// 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
Wyatt Hepler74e7ab62021-06-15 19:44:32 -070015#include "pw_rpc/internal/responder.h"
Wyatt Heplercb9d9572020-06-01 11:25:58 -070016
Wyatt Heplerf298de42021-03-19 15:06:36 -070017#include "pw_assert/check.h"
Wyatt Heplercb9d9572020-06-01 11:25:58 -070018#include "pw_rpc/internal/method.h"
19#include "pw_rpc/internal/packet.h"
Wyatt Hepler60fd70f2020-06-17 09:04:25 -070020#include "pw_rpc/internal/server.h"
Wyatt Heplercb9d9572020-06-01 11:25:58 -070021
22namespace pw::rpc::internal {
Wyatt Hepler5ba80642021-06-18 12:56:17 -070023namespace {
24
25Packet ResponsePacket(const ServerCall& call,
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070026 std::span<const std::byte> payload,
Wyatt Hepler5ba80642021-06-18 12:56:17 -070027 Status status) {
28 return Packet(PacketType::RESPONSE,
29 call.channel().id(),
30 call.service().id(),
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070031 call.method().id(),
32 payload,
Wyatt Hepler5ba80642021-06-18 12:56:17 -070033 status);
34}
35
36Packet StreamPacket(const ServerCall& call,
Wyatt Hepler5ba80642021-06-18 12:56:17 -070037 std::span<const std::byte> payload) {
38 return Packet(PacketType::SERVER_STREAM,
39 call.channel().id(),
40 call.service().id(),
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070041 call.method().id(),
Wyatt Hepler5ba80642021-06-18 12:56:17 -070042 payload);
43}
44
45} // namespace
Wyatt Heplercb9d9572020-06-01 11:25:58 -070046
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070047Responder::Responder(ServerCall& call, HasClientStream has_client_stream)
48 : call_(call),
49 rpc_state_(kOpen),
50 has_client_stream_(has_client_stream),
51 client_stream_state_(has_client_stream ? kClientStreamOpen
52 : kClientStreamClosed) {
Wyatt Hepler5180fe22021-06-15 19:32:08 -070053 call_.server().RegisterResponder(*this);
Wyatt Hepler60fd70f2020-06-17 09:04:25 -070054}
55
Wyatt Hepler5180fe22021-06-15 19:32:08 -070056Responder& Responder::operator=(Responder&& other) {
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070057 CloseAndSendResponse(OkStatus()).IgnoreError();
Wyatt Heplerb7643d72020-07-10 10:33:14 -070058
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070059 // Move the state variables, which may change when the other client closes.
60 rpc_state_ = other.rpc_state_;
61 has_client_stream_ = other.has_client_stream_;
62 client_stream_state_ = other.client_stream_state_;
Wyatt Heplerb7643d72020-07-10 10:33:14 -070063
64 if (other.open()) {
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070065 other.Close();
Wyatt Hepler5180fe22021-06-15 19:32:08 -070066 other.call_.server().RegisterResponder(*this);
Wyatt Heplerb7643d72020-07-10 10:33:14 -070067 }
68
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070069 // Move the rest of the member variables.
Wyatt Hepler671946e2020-06-09 14:39:33 -070070 call_ = std::move(other.call_);
Wyatt Heplercb9d9572020-06-01 11:25:58 -070071 response_ = std::move(other.response_);
Wyatt Hepler671946e2020-06-09 14:39:33 -070072
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070073 on_error_ = std::move(other.on_error_);
74 on_next_ = std::move(other.on_next_);
75 on_client_stream_end_ = std::move(other.on_client_stream_end_);
76
Wyatt Heplercb9d9572020-06-01 11:25:58 -070077 return *this;
78}
79
Wyatt Hepler5180fe22021-06-15 19:32:08 -070080uint32_t Responder::method_id() const { return call_.method().id(); }
Wyatt Hepleraf835682020-06-17 11:42:53 -070081
Wyatt Hepler59b37f72021-06-15 16:23:44 -070082Status Responder::CloseAndSendResponse(std::span<const std::byte> response,
83 Status status) {
Wyatt Hepler671946e2020-06-09 14:39:33 -070084 if (!open()) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -080085 return Status::FailedPrecondition();
Wyatt Heplercb9d9572020-06-01 11:25:58 -070086 }
Wyatt Hepler671946e2020-06-09 14:39:33 -070087
Wyatt Hepler59b37f72021-06-15 16:23:44 -070088 // Send a packet indicating that the RPC has terminated.
89 Status packet_status =
90 call_.channel().Send(ResponsePacket(call_, response, status));
91
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070092 // If the Responder implementer or user forgets to release an acquired buffer
93 // before finishing, release it here.
Alexei Frolovb3701c22020-11-04 11:30:47 -080094 if (!response_.empty()) {
95 ReleasePayloadBuffer();
96 }
97
Alexei Frolov062ed182020-09-28 16:23:06 -070098 Close();
Wyatt Hepleraf835682020-06-17 11:42:53 -070099
Wyatt Hepler59b37f72021-06-15 16:23:44 -0700100 return packet_status;
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700101}
102
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700103std::span<std::byte> Responder::AcquirePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800104 PW_DCHECK(open());
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700105
Alexei Frolovb3701c22020-11-04 11:30:47 -0800106 // Only allow having one active buffer at a time.
107 if (response_.empty()) {
108 response_ = call_.channel().AcquireBuffer();
109 }
110
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700111 return response_.payload(StreamPacket(call_, {}));
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700112}
113
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700114Status Responder::ReleasePayloadBuffer(std::span<const std::byte> payload) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800115 PW_DCHECK(open());
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700116 return call_.channel().Send(response_, StreamPacket(call_, payload));
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700117}
118
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700119Status Responder::ReleasePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800120 PW_DCHECK(open());
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800121 call_.channel().Release(response_);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800122 return OkStatus();
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800123}
124
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700125void Responder::Close() {
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700126 PW_DCHECK(open());
Alexei Frolov062ed182020-09-28 16:23:06 -0700127
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700128 call_.server().RemoveResponder(*this);
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700129 rpc_state_ = kClosed;
130 client_stream_state_ = kClientStreamClosed;
Alexei Frolov062ed182020-09-28 16:23:06 -0700131}
132
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700133} // namespace pw::rpc::internal