blob: be9abb718c09dea89f047f08a339e9c632defba0 [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,
26 uint32_t method_id,
27 Status status) {
28 return Packet(PacketType::RESPONSE,
29 call.channel().id(),
30 call.service().id(),
31 method_id,
32 {},
33 status);
34}
35
36Packet StreamPacket(const ServerCall& call,
37 uint32_t method_id,
38 std::span<const std::byte> payload) {
39 return Packet(PacketType::SERVER_STREAM,
40 call.channel().id(),
41 call.service().id(),
42 method_id,
43 payload);
44}
45
46} // namespace
Wyatt Heplercb9d9572020-06-01 11:25:58 -070047
Wyatt Hepler5180fe22021-06-15 19:32:08 -070048Responder::Responder(ServerCall& call) : call_(call), state_(kOpen) {
49 call_.server().RegisterResponder(*this);
Wyatt Hepler60fd70f2020-06-17 09:04:25 -070050}
51
Wyatt Hepler5180fe22021-06-15 19:32:08 -070052Responder& Responder::operator=(Responder&& other) {
Wyatt Heplerb7643d72020-07-10 10:33:14 -070053 Finish();
54
55 state_ = other.state_;
56
57 if (other.open()) {
Wyatt Hepler5180fe22021-06-15 19:32:08 -070058 other.call_.server().RemoveResponder(other);
Wyatt Heplerb7643d72020-07-10 10:33:14 -070059 other.state_ = kClosed;
60
Wyatt Hepler5180fe22021-06-15 19:32:08 -070061 other.call_.server().RegisterResponder(*this);
Wyatt Heplerb7643d72020-07-10 10:33:14 -070062 }
63
Wyatt Hepler671946e2020-06-09 14:39:33 -070064 call_ = std::move(other.call_);
Wyatt Heplercb9d9572020-06-01 11:25:58 -070065 response_ = std::move(other.response_);
Wyatt Hepler671946e2020-06-09 14:39:33 -070066
Wyatt Heplercb9d9572020-06-01 11:25:58 -070067 return *this;
68}
69
Wyatt Hepler5180fe22021-06-15 19:32:08 -070070uint32_t Responder::method_id() const { return call_.method().id(); }
Wyatt Hepleraf835682020-06-17 11:42:53 -070071
Wyatt Hepler5180fe22021-06-15 19:32:08 -070072Status Responder::Finish(Status status) {
Wyatt Hepler671946e2020-06-09 14:39:33 -070073 if (!open()) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -080074 return Status::FailedPrecondition();
Wyatt Heplercb9d9572020-06-01 11:25:58 -070075 }
Wyatt Hepler671946e2020-06-09 14:39:33 -070076
Wyatt Hepler5180fe22021-06-15 19:32:08 -070077 // If the Responder implementer or user forgets to release an acquired
Alexei Frolovb3701c22020-11-04 11:30:47 -080078 // buffer before finishing, release it here.
79 if (!response_.empty()) {
80 ReleasePayloadBuffer();
81 }
82
Alexei Frolov062ed182020-09-28 16:23:06 -070083 Close();
Wyatt Hepleraf835682020-06-17 11:42:53 -070084
Wyatt Hepler5ba80642021-06-18 12:56:17 -070085 // Send a packet indicating that the RPC has terminated.
86 return call_.channel().Send(ResponsePacket(call_, method_id(), status));
Wyatt Heplercb9d9572020-06-01 11:25:58 -070087}
88
Wyatt Hepler5180fe22021-06-15 19:32:08 -070089std::span<std::byte> Responder::AcquirePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -080090 PW_DCHECK(open());
Wyatt Heplercb9d9572020-06-01 11:25:58 -070091
Alexei Frolovb3701c22020-11-04 11:30:47 -080092 // Only allow having one active buffer at a time.
93 if (response_.empty()) {
94 response_ = call_.channel().AcquireBuffer();
95 }
96
Wyatt Hepler5ba80642021-06-18 12:56:17 -070097 return response_.payload(StreamPacket(call_, method_id(), {}));
Wyatt Heplercb9d9572020-06-01 11:25:58 -070098}
99
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700100Status Responder::ReleasePayloadBuffer(std::span<const std::byte> payload) {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800101 PW_DCHECK(open());
Wyatt Hepler5ba80642021-06-18 12:56:17 -0700102 return call_.channel().Send(response_,
103 StreamPacket(call_, method_id(), payload));
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700104}
105
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700106Status Responder::ReleasePayloadBuffer() {
Wyatt Heplerd08e5822021-02-18 17:53:38 -0800107 PW_DCHECK(open());
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800108 call_.channel().Release(response_);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800109 return OkStatus();
Alexei Frolov909bdfa2020-11-03 16:21:47 -0800110}
111
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700112void Responder::Close() {
Alexei Frolov062ed182020-09-28 16:23:06 -0700113 if (!open()) {
114 return;
115 }
116
Wyatt Hepler5180fe22021-06-15 19:32:08 -0700117 call_.server().RemoveResponder(*this);
Alexei Frolov062ed182020-09-28 16:23:06 -0700118 state_ = kClosed;
119}
120
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700121} // namespace pw::rpc::internal