blob: e4afcb5de5b1515d8ea6a5877b0ba6c5f8d6eab6 [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 Heplerff2ca832021-09-03 17:20:40 -070015#include "pw_rpc/internal/call.h"
Wyatt Heplercb9d9572020-06-01 11:25:58 -070016
Wyatt Heplerf298de42021-03-19 15:06:36 -070017#include "pw_assert/check.h"
Wyatt Hepler82db4b12021-09-23 09:10:12 -070018#include "pw_rpc/client.h"
Wyatt Hepler960f5df2021-09-08 10:17:21 -070019#include "pw_rpc/internal/endpoint.h"
Wyatt Heplercb9d9572020-06-01 11:25:58 -070020#include "pw_rpc/internal/method.h"
Wyatt Heplerddfc0772021-09-03 16:46:25 -070021#include "pw_rpc/server.h"
Wyatt Heplercb9d9572020-06-01 11:25:58 -070022
23namespace pw::rpc::internal {
24
Alexei Frolov86e05de2021-10-19 16:52:31 -070025// Creates an active client-side call, assigning it a new ID.
26Call::Call(Endpoint& client,
27 uint32_t channel_id,
28 uint32_t service_id,
29 uint32_t method_id,
30 MethodType type)
31 : Call(client,
32 client.NewCallId(),
33 channel_id,
34 service_id,
35 method_id,
36 type,
37 kClientCall) {}
38
Wyatt Hepler82db4b12021-09-23 09:10:12 -070039Call::Call(Endpoint& endpoint_ref,
Alexei Frolov86e05de2021-10-19 16:52:31 -070040 uint32_t call_id,
Wyatt Hepler82db4b12021-09-23 09:10:12 -070041 uint32_t channel_id,
42 uint32_t service_id,
43 uint32_t method_id,
44 MethodType type,
45 CallType call_type)
46 : endpoint_(&endpoint_ref),
Wyatt Hepler592b5a12022-02-01 17:55:21 -080047 channel_id_(channel_id),
Alexei Frolov86e05de2021-10-19 16:52:31 -070048 id_(call_id),
Wyatt Hepler82db4b12021-09-23 09:10:12 -070049 service_id_(service_id),
50 method_id_(method_id),
Wyatt Hepler5a3a36b2021-09-08 11:15:05 -070051 rpc_state_(kActive),
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -070052 type_(type),
Wyatt Hepler82db4b12021-09-23 09:10:12 -070053 call_type_(call_type),
Wyatt Hepler5a3a36b2021-09-08 11:15:05 -070054 client_stream_state_(HasClientStream(type) ? kClientStreamActive
55 : kClientStreamInactive) {
Wyatt Hepler960f5df2021-09-08 10:17:21 -070056 endpoint().RegisterCall(*this);
Wyatt Hepler60fd70f2020-06-17 09:04:25 -070057}
58
Wyatt Hepler960f5df2021-09-08 10:17:21 -070059void Call::MoveFrom(Call& other) {
Wyatt Heplerb1c47992022-01-06 11:05:50 -080060 PW_DCHECK(!active_locked());
Wyatt Heplerb7643d72020-07-10 10:33:14 -070061
Wyatt Heplerb1c47992022-01-06 11:05:50 -080062 if (!other.active_locked()) {
Wyatt Heplera2154152021-10-21 08:09:30 -070063 return; // Nothing else to do; this call is already closed.
64 }
Wyatt Heplerb7643d72020-07-10 10:33:14 -070065
Wyatt Heplera2154152021-10-21 08:09:30 -070066 // Copy all members from the other call.
Wyatt Hepler960f5df2021-09-08 10:17:21 -070067 endpoint_ = other.endpoint_;
Wyatt Hepler592b5a12022-02-01 17:55:21 -080068 channel_id_ = other.channel_id_;
Alexei Frolov86e05de2021-10-19 16:52:31 -070069 id_ = other.id_;
Wyatt Hepler960f5df2021-09-08 10:17:21 -070070 service_id_ = other.service_id_;
71 method_id_ = other.method_id_;
72
Wyatt Heplera2154152021-10-21 08:09:30 -070073 rpc_state_ = other.rpc_state_;
74 type_ = other.type_;
75 call_type_ = other.call_type_;
76 client_stream_state_ = other.client_stream_state_;
Wyatt Hepler960f5df2021-09-08 10:17:21 -070077
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070078 on_error_ = std::move(other.on_error_);
79 on_next_ = std::move(other.on_next_);
Wyatt Heplera2154152021-10-21 08:09:30 -070080
81 // Mark the other call inactive, unregister it, and register this one.
82 other.rpc_state_ = kInactive;
83 other.client_stream_state_ = kClientStreamInactive;
84
85 endpoint().UnregisterCall(other);
86 endpoint().RegisterUniqueCall(*this);
Wyatt Heplercb9d9572020-06-01 11:25:58 -070087}
88
Wyatt Hepler592b5a12022-02-01 17:55:21 -080089Status Call::SendPacket(PacketType type, ConstByteSpan payload, Status status) {
Wyatt Heplere4ce9942022-02-02 09:16:20 -080090 if (!active_locked()) {
91 return Status::FailedPrecondition();
92 }
93
Wyatt Hepler592b5a12022-02-01 17:55:21 -080094 Channel* channel = endpoint_->GetInternalChannel(channel_id_);
95 if (channel == nullptr) {
96 return Status::Unavailable();
97 }
98 return channel->Send(MakePacket(type, payload, status));
99}
100
Wyatt Hepler0c87be52022-01-13 08:33:43 -0800101Status Call::CloseAndSendFinalPacketLocked(PacketType type,
102 ConstByteSpan response,
103 Status status) {
Wyatt Heplere4ce9942022-02-02 09:16:20 -0800104 const Status send_status = SendPacket(type, response, status);
Wyatt Hepler0c87be52022-01-13 08:33:43 -0800105 UnregisterAndMarkClosed();
Wyatt Heplere4ce9942022-02-02 09:16:20 -0800106 return send_status;
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700107}
108
Wyatt Hepleraf16dbb2022-01-27 20:15:15 -0800109Status Call::WriteLocked(ConstByteSpan payload) {
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700110 return SendPacket(call_type_ == kServerCall ? PacketType::SERVER_STREAM
111 : PacketType::CLIENT_STREAM,
112 payload);
113}
114
Wyatt Hepler0c87be52022-01-13 08:33:43 -0800115void Call::UnregisterAndMarkClosed() {
Wyatt Heplerb1c47992022-01-06 11:05:50 -0800116 if (active_locked()) {
Wyatt Heplera2154152021-10-21 08:09:30 -0700117 endpoint().UnregisterCall(*this);
Wyatt Hepler3d57eaa2022-02-01 18:31:07 -0800118 MarkClosed();
Wyatt Heplera2154152021-10-21 08:09:30 -0700119 }
Alexei Frolov062ed182020-09-28 16:23:06 -0700120}
121
Wyatt Heplercb9d9572020-06-01 11:25:58 -0700122} // namespace pw::rpc::internal