blob: 896799d2b3ae4d59f65c5bffe0f159cc6f772e40 [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
Wyatt Hepler29332d92021-09-02 07:49:53 -070025Packet ResponsePacket(const CallContext& 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
Wyatt Hepler29332d92021-09-02 07:49:53 -070036Packet StreamPacket(const CallContext& 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 Hepler29332d92021-09-02 07:49:53 -070047Responder::Responder(const CallContext& call, MethodType type)
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070048 : call_(call),
49 rpc_state_(kOpen),
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -070050 type_(type),
51 client_stream_state_(HasClientStream(type) ? 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 Hepler68daa722021-07-15 17:10:15 -070057 // If this RPC was running, complete it before moving in the other RPC.
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -070058 CloseAndSendResponse(OkStatus()).IgnoreError();
Wyatt Heplerb7643d72020-07-10 10:33:14 -070059
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070060 // Move the state variables, which may change when the other client closes.
61 rpc_state_ = other.rpc_state_;
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -070062 type_ = other.type_;
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070063 client_stream_state_ = other.client_stream_state_;
Wyatt Heplerb7643d72020-07-10 10:33:14 -070064
65 if (other.open()) {
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070066 other.Close();
Wyatt Hepler5180fe22021-06-15 19:32:08 -070067 other.call_.server().RegisterResponder(*this);
Wyatt Heplerb7643d72020-07-10 10:33:14 -070068 }
69
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070070 // Move the rest of the member variables.
Wyatt Hepler671946e2020-06-09 14:39:33 -070071 call_ = std::move(other.call_);
Wyatt Heplercb9d9572020-06-01 11:25:58 -070072 response_ = std::move(other.response_);
Wyatt Hepler671946e2020-06-09 14:39:33 -070073
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070074 on_error_ = std::move(other.on_error_);
75 on_next_ = std::move(other.on_next_);
Wyatt Hepler379b2fc2021-06-22 22:54:33 -070076
77#if PW_RPC_CLIENT_STREAM_END_CALLBACK
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070078 on_client_stream_end_ = std::move(other.on_client_stream_end_);
Wyatt Hepler379b2fc2021-06-22 22:54:33 -070079#endif // PW_RPC_CLIENT_STREAM_END_CALLBACK
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070080
Wyatt Heplercb9d9572020-06-01 11:25:58 -070081 return *this;
82}
83
Wyatt Hepler5180fe22021-06-15 19:32:08 -070084uint32_t Responder::method_id() const { return call_.method().id(); }
Wyatt Hepleraf835682020-06-17 11:42:53 -070085
Wyatt Hepler59b37f72021-06-15 16:23:44 -070086Status Responder::CloseAndSendResponse(std::span<const std::byte> response,
87 Status status) {
Wyatt Hepler671946e2020-06-09 14:39:33 -070088 if (!open()) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -080089 return Status::FailedPrecondition();
Wyatt Heplercb9d9572020-06-01 11:25:58 -070090 }
Wyatt Hepler671946e2020-06-09 14:39:33 -070091
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -070092 Status packet_status;
Wyatt Hepler59b37f72021-06-15 16:23:44 -070093
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -070094 // Acquire a buffer to use for the outgoing packet if none is available.
95 if (response_.empty()) {
96 response_ = call_.channel().AcquireBuffer();
Alexei Frolovb3701c22020-11-04 11:30:47 -080097 }
98
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -070099 // Send a packet indicating that the RPC has terminated and optionally
100 // containing the final payload.
101 packet_status =
102 call_.channel().Send(response_, ResponsePacket(call_, response, status));
103
Alexei Frolov062ed182020-09-28 16:23:06 -0700104 Close();
Wyatt Hepleraf835682020-06-17 11:42:53 -0700105
Wyatt Hepler59b37f72021-06-15 16:23:44 -0700106 return packet_status;
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700107}
108
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700109std::span<std::byte> Responder::AcquirePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800110 PW_DCHECK(open());
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700111
Alexei Frolovb3701c22020-11-04 11:30:47 -0800112 // Only allow having one active buffer at a time.
113 if (response_.empty()) {
114 response_ = call_.channel().AcquireBuffer();
115 }
116
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700117 return response_.payload(StreamPacket(call_, {}));
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700118}
119
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -0700120Status Responder::SendPayloadBufferClientStream(
121 std::span<const std::byte> payload) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800122 PW_DCHECK(open());
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700123 return call_.channel().Send(response_, StreamPacket(call_, payload));
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700124}
125
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -0700126void Responder::ReleasePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800127 PW_DCHECK(open());
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800128 call_.channel().Release(response_);
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800129}
130
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700131void Responder::Close() {
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700132 PW_DCHECK(open());
Alexei Frolov062ed182020-09-28 16:23:06 -0700133
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700134 call_.server().RemoveResponder(*this);
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700135 rpc_state_ = kClosed;
136 client_stream_state_ = kClientStreamClosed;
Alexei Frolov062ed182020-09-28 16:23:06 -0700137}
138
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700139} // namespace pw::rpc::internal