blob: 575fa3aa48f39269c695c2039ad830dd38559c79 [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_);
Wyatt Hepler379b2fc2021-06-22 22:54:33 -070075
76#if PW_RPC_CLIENT_STREAM_END_CALLBACK
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070077 on_client_stream_end_ = std::move(other.on_client_stream_end_);
Wyatt Hepler379b2fc2021-06-22 22:54:33 -070078#endif // PW_RPC_CLIENT_STREAM_END_CALLBACK
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070079
Wyatt Heplercb9d9572020-06-01 11:25:58 -070080 return *this;
81}
82
Wyatt Hepler5180fe22021-06-15 19:32:08 -070083uint32_t Responder::method_id() const { return call_.method().id(); }
Wyatt Hepleraf835682020-06-17 11:42:53 -070084
Wyatt Hepler59b37f72021-06-15 16:23:44 -070085Status Responder::CloseAndSendResponse(std::span<const std::byte> response,
86 Status status) {
Wyatt Hepler671946e2020-06-09 14:39:33 -070087 if (!open()) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -080088 return Status::FailedPrecondition();
Wyatt Heplercb9d9572020-06-01 11:25:58 -070089 }
Wyatt Hepler671946e2020-06-09 14:39:33 -070090
Wyatt Hepler59b37f72021-06-15 16:23:44 -070091 // Send a packet indicating that the RPC has terminated.
92 Status packet_status =
93 call_.channel().Send(ResponsePacket(call_, response, status));
94
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070095 // If the Responder implementer or user forgets to release an acquired buffer
96 // before finishing, release it here.
Alexei Frolovb3701c22020-11-04 11:30:47 -080097 if (!response_.empty()) {
98 ReleasePayloadBuffer();
99 }
100
Alexei Frolov062ed182020-09-28 16:23:06 -0700101 Close();
Wyatt Hepleraf835682020-06-17 11:42:53 -0700102
Wyatt Hepler59b37f72021-06-15 16:23:44 -0700103 return packet_status;
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700104}
105
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700106std::span<std::byte> Responder::AcquirePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800107 PW_DCHECK(open());
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700108
Alexei Frolovb3701c22020-11-04 11:30:47 -0800109 // Only allow having one active buffer at a time.
110 if (response_.empty()) {
111 response_ = call_.channel().AcquireBuffer();
112 }
113
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700114 return response_.payload(StreamPacket(call_, {}));
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700115}
116
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700117Status Responder::ReleasePayloadBuffer(std::span<const std::byte> payload) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800118 PW_DCHECK(open());
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700119 return call_.channel().Send(response_, StreamPacket(call_, payload));
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700120}
121
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700122Status Responder::ReleasePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800123 PW_DCHECK(open());
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800124 call_.channel().Release(response_);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800125 return OkStatus();
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800126}
127
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700128void Responder::Close() {
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700129 PW_DCHECK(open());
Alexei Frolov062ed182020-09-28 16:23:06 -0700130
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700131 call_.server().RemoveResponder(*this);
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700132 rpc_state_ = kClosed;
133 client_stream_state_ = kClientStreamClosed;
Alexei Frolov062ed182020-09-28 16:23:06 -0700134}
135
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700136} // namespace pw::rpc::internal