blob: 78681b53fed8eda52163af9f1f1156d769cf1571 [file] [log] [blame]
Alexei Frolov5d6d3922020-05-08 13:57:02 -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
Ewout van Bekkum7f5b3052021-11-11 17:35:23 -080015// clang-format off
16#include "pw_rpc/internal/log_config.h" // PW_LOG_* macros must be first.
17
Alexei Frolov5d6d3922020-05-08 13:57:02 -070018#include "pw_rpc/server.h"
Ewout van Bekkum7f5b3052021-11-11 17:35:23 -080019// clang-format on
Alexei Frolov5d6d3922020-05-08 13:57:02 -070020
Wyatt Hepler3e2d7192020-06-11 08:28:21 -070021#include <algorithm>
22
Alexei Frolov5d6d3922020-05-08 13:57:02 -070023#include "pw_log/log.h"
Wyatt Heplerddfc0772021-09-03 16:46:25 -070024#include "pw_rpc/internal/endpoint.h"
Alexei Frolov5d6d3922020-05-08 13:57:02 -070025#include "pw_rpc/internal/packet.h"
26
27namespace pw::rpc {
Wyatt Hepler712d3672020-07-13 15:52:11 -070028namespace {
Alexei Frolov5d6d3922020-05-08 13:57:02 -070029
30using internal::Packet;
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070031using internal::PacketType;
Alexei Frolov5d6d3922020-05-08 13:57:02 -070032
Wyatt Hepler712d3672020-07-13 15:52:11 -070033} // namespace
34
Alexei Frolovba93a432021-12-02 13:36:26 -080035Status Server::ProcessPacket(ConstByteSpan packet_data,
36 ChannelOutput* interface) {
Wyatt Hepler1d000cc2021-10-20 11:05:06 -070037 PW_TRY_ASSIGN(Result<Packet> result,
Ted Pudlik4180d4d2021-10-28 00:07:29 +000038 Endpoint::ProcessPacket(packet_data, Packet::kServer));
Wyatt Heplerddfc0772021-09-03 16:46:25 -070039 Packet& packet = *result;
Alexei Frolov5d6d3922020-05-08 13:57:02 -070040
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070041 internal::rpc_lock().lock();
Wyatt Hepler1d000cc2021-10-20 11:05:06 -070042 internal::ServerCall* const call =
43 static_cast<internal::ServerCall*>(FindCall(packet));
44
Wyatt Hepler3aab7f62021-10-05 16:14:51 -070045 // Verbose log for debugging.
46 // PW_LOG_DEBUG("RPC server received packet type %u for %u:%08x/%08x",
47 // static_cast<unsigned>(packet.type()),
48 // static_cast<unsigned>(packet.channel_id()),
49 // static_cast<unsigned>(packet.service_id()),
50 // static_cast<unsigned>(packet.method_id()));
51
Wyatt Heplerddfc0772021-09-03 16:46:25 -070052 internal::Channel* channel = GetInternalChannel(packet.channel_id());
Alexei Frolov5d6d3922020-05-08 13:57:02 -070053 if (channel == nullptr) {
Wyatt Hepler3d57eaa2022-02-01 18:31:07 -080054 // If an interface was provided, respond with a SERVER_ERROR to indicate
55 // that the channel is not available on this server. Don't send responses to
56 // error messages, though, to avoid potential infinite cycles.
57 if (interface != nullptr && packet.type() != PacketType::CLIENT_ERROR) {
58 internal::Channel(packet.channel_id(), interface)
59 .Send(Packet::ServerError(packet, Status::Unavailable()))
60 .IgnoreError();
Alexei Frolovba93a432021-12-02 13:36:26 -080061 }
62
Wyatt Hepler3d57eaa2022-02-01 18:31:07 -080063 internal::rpc_lock().unlock();
64 PW_LOG_WARN("RPC server received packet for unknown channel %u",
65 static_cast<unsigned>(packet.channel_id()));
66 return Status::Unavailable();
Alexei Frolov5d6d3922020-05-08 13:57:02 -070067 }
68
Wyatt Hepler0f262352020-07-29 09:51:27 -070069 const auto [service, method] = FindMethod(packet);
70
71 if (method == nullptr) {
Wyatt Hepler3be460d2021-09-09 16:28:12 -070072 // Don't send responses to errors to avoid infinite error cycles.
73 if (packet.type() != PacketType::CLIENT_ERROR) {
74 channel->Send(Packet::ServerError(packet, Status::NotFound()))
75 .IgnoreError();
76 }
Wyatt Hepleraf16dbb2022-01-27 20:15:15 -080077 internal::rpc_lock().unlock();
Wyatt Hepler3be460d2021-09-09 16:28:12 -070078 return OkStatus(); // OK since the packet was handled.
Wyatt Hepler0f262352020-07-29 09:51:27 -070079 }
80
81 switch (packet.type()) {
82 case PacketType::REQUEST: {
Wyatt Hepler960f5df2021-09-08 10:17:21 -070083 // If the REQUEST is for an ongoing RPC, the existing call will be
84 // cancelled when the new call object is created.
Alexei Frolov86e05de2021-10-19 16:52:31 -070085 const internal::CallContext context(
Wyatt Hepler592b5a12022-02-01 17:55:21 -080086 *this, channel->id(), *service, *method, packet.call_id());
Wyatt Heplerddfc0772021-09-03 16:46:25 -070087 method->Invoke(context, packet);
Wyatt Hepler0f262352020-07-29 09:51:27 -070088 break;
89 }
Wyatt Heplera9211162021-06-12 15:40:11 -070090 case PacketType::CLIENT_STREAM:
Wyatt Heplerddfc0772021-09-03 16:46:25 -070091 HandleClientStreamPacket(packet, *channel, call);
Wyatt Hepler0f262352020-07-29 09:51:27 -070092 break;
93 case PacketType::CLIENT_ERROR:
Wyatt Hepler17169152021-10-20 18:46:08 -070094 case PacketType::DEPRECATED_CANCEL:
Alexei Frolov86e05de2021-10-19 16:52:31 -070095 if (call != nullptr && call->id() == packet.call_id()) {
Wyatt Heplerddfc0772021-09-03 16:46:25 -070096 call->HandleError(packet.status());
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070097 } else {
98 internal::rpc_lock().unlock();
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070099 }
Wyatt Hepler0f262352020-07-29 09:51:27 -0700100 break;
Wyatt Heplera9211162021-06-12 15:40:11 -0700101 case PacketType::CLIENT_STREAM_END:
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700102 HandleClientStreamPacket(packet, *channel, call);
Wyatt Heplera9211162021-06-12 15:40:11 -0700103 break;
Wyatt Hepler0f262352020-07-29 09:51:27 -0700104 default:
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -0700105 internal::rpc_lock().unlock();
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700106 PW_LOG_WARN("pw_rpc server unable to handle packet of type %u",
Wyatt Hepler0f262352020-07-29 09:51:27 -0700107 unsigned(packet.type()));
108 }
Wyatt Hepler1d000cc2021-10-20 11:05:06 -0700109
110 return OkStatus(); // OK since the packet was handled
Wyatt Hepler0f262352020-07-29 09:51:27 -0700111}
112
Wyatt Heplercbd09c22020-09-15 11:17:24 -0700113std::tuple<Service*, const internal::Method*> Server::FindMethod(
Wyatt Hepler0f262352020-07-29 09:51:27 -0700114 const internal::Packet& packet) {
Wyatt Hepler712d3672020-07-13 15:52:11 -0700115 // Packets always include service and method IDs.
Wyatt Hepler3e2d7192020-06-11 08:28:21 -0700116 auto service = std::find_if(services_.begin(), services_.end(), [&](auto& s) {
Wyatt Hepler712d3672020-07-13 15:52:11 -0700117 return s.id() == packet.service_id();
Wyatt Hepler3e2d7192020-06-11 08:28:21 -0700118 });
119
120 if (service == services_.end()) {
Wyatt Hepler0f262352020-07-29 09:51:27 -0700121 return {};
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700122 }
123
Wyatt Hepler0f262352020-07-29 09:51:27 -0700124 return {&(*service), service->FindMethod(packet.method_id())};
Wyatt Hepler712d3672020-07-13 15:52:11 -0700125}
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700126
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700127void Server::HandleClientStreamPacket(const internal::Packet& packet,
128 internal::Channel& channel,
Wyatt Hepler960f5df2021-09-08 10:17:21 -0700129 internal::ServerCall* call) const {
Alexei Frolov86e05de2021-10-19 16:52:31 -0700130 if (call == nullptr || call->id() != packet.call_id()) {
Wyatt Heplerb1c47992022-01-06 11:05:50 -0800131 channel.Send(Packet::ServerError(packet, Status::FailedPrecondition()))
132 .IgnoreError(); // Errors are logged in Channel::Send.
Wyatt Hepleraf16dbb2022-01-27 20:15:15 -0800133 internal::rpc_lock().unlock();
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700134 PW_LOG_DEBUG(
Wyatt Hepler3aab7f62021-10-05 16:14:51 -0700135 "Received client stream packet for %u:%08x/%08x, which is not pending",
136 static_cast<unsigned>(packet.channel_id()),
137 static_cast<unsigned>(packet.service_id()),
138 static_cast<unsigned>(packet.method_id()));
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700139 return;
140 }
141
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700142 if (!call->has_client_stream()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000143 channel.Send(Packet::ServerError(packet, Status::InvalidArgument()))
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700144 .IgnoreError(); // Errors are logged in Channel::Send.
Wyatt Hepleraf16dbb2022-01-27 20:15:15 -0800145 internal::rpc_lock().unlock();
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700146 return;
147 }
148
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700149 if (!call->client_stream_open()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000150 channel.Send(Packet::ServerError(packet, Status::FailedPrecondition()))
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700151 .IgnoreError(); // Errors are logged in Channel::Send.
Wyatt Hepleraf16dbb2022-01-27 20:15:15 -0800152 internal::rpc_lock().unlock();
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700153 return;
154 }
155
156 if (packet.type() == PacketType::CLIENT_STREAM) {
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700157 call->HandlePayload(packet.payload());
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700158 } else { // Handle PacketType::CLIENT_STREAM_END.
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -0700159 call->HandleClientStreamEnd();
Wyatt Hepler712d3672020-07-13 15:52:11 -0700160 }
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700161}
162
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700163} // namespace pw::rpc