blob: 6f4b78cfd6e9e2904a03109e8dce00d0b7f9d3aa [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 Hepler01fc15b2021-06-10 18:15:59 -070082Status Responder::CloseAndSendResponse(Status status) {
Wyatt Hepler671946e2020-06-09 14:39:33 -070083 if (!open()) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -080084 return Status::FailedPrecondition();
Wyatt Heplercb9d9572020-06-01 11:25:58 -070085 }
Wyatt Hepler671946e2020-06-09 14:39:33 -070086
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070087 // If the Responder implementer or user forgets to release an acquired buffer
88 // before finishing, release it here.
Alexei Frolovb3701c22020-11-04 11:30:47 -080089 if (!response_.empty()) {
90 ReleasePayloadBuffer();
91 }
92
Alexei Frolov062ed182020-09-28 16:23:06 -070093 Close();
Wyatt Hepleraf835682020-06-17 11:42:53 -070094
Wyatt Hepler5ba80642021-06-18 12:56:17 -070095 // Send a packet indicating that the RPC has terminated.
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070096 return call_.channel().Send(ResponsePacket(call_, {}, status));
Wyatt Heplercb9d9572020-06-01 11:25:58 -070097}
98
Wyatt Hepler5180fe22021-06-15 19:32:08 -070099std::span<std::byte> Responder::AcquirePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800100 PW_DCHECK(open());
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700101
Alexei Frolovb3701c22020-11-04 11:30:47 -0800102 // Only allow having one active buffer at a time.
103 if (response_.empty()) {
104 response_ = call_.channel().AcquireBuffer();
105 }
106
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700107 return response_.payload(StreamPacket(call_, {}));
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700108}
109
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700110Status Responder::ReleasePayloadBuffer(std::span<const std::byte> payload) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800111 PW_DCHECK(open());
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700112 return call_.channel().Send(response_, StreamPacket(call_, payload));
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700113}
114
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700115Status Responder::ReleasePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800116 PW_DCHECK(open());
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800117 call_.channel().Release(response_);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800118 return OkStatus();
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800119}
120
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700121void Responder::Close() {
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700122 PW_DCHECK(open());
Alexei Frolov062ed182020-09-28 16:23:06 -0700123
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700124 call_.server().RemoveResponder(*this);
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700125 rpc_state_ = kClosed;
126 client_stream_state_ = kClientStreamClosed;
Alexei Frolov062ed182020-09-28 16:23:06 -0700127}
128
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700129} // namespace pw::rpc::internal