blob: 5a45a361a67d07acecf7d4f585b2ced3017c4efc [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>
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070022#include <mutex>
Wyatt Hepler3e2d7192020-06-11 08:28:21 -070023
Alexei Frolov5d6d3922020-05-08 13:57:02 -070024#include "pw_log/log.h"
Wyatt Heplerddfc0772021-09-03 16:46:25 -070025#include "pw_rpc/internal/endpoint.h"
Alexei Frolov5d6d3922020-05-08 13:57:02 -070026#include "pw_rpc/internal/packet.h"
27
28namespace pw::rpc {
Wyatt Hepler712d3672020-07-13 15:52:11 -070029namespace {
Alexei Frolov5d6d3922020-05-08 13:57:02 -070030
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070031using std::byte;
32
Alexei Frolov5d6d3922020-05-08 13:57:02 -070033using internal::Packet;
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070034using internal::PacketType;
Alexei Frolov5d6d3922020-05-08 13:57:02 -070035
Wyatt Hepler712d3672020-07-13 15:52:11 -070036} // namespace
37
Ted Pudlik4180d4d2021-10-28 00:07:29 +000038Status Server::ProcessPacket(std::span<const byte> packet_data,
Wyatt Hepler0f262352020-07-29 09:51:27 -070039 ChannelOutput& interface) {
Wyatt Hepler1d000cc2021-10-20 11:05:06 -070040 PW_TRY_ASSIGN(Result<Packet> result,
Ted Pudlik4180d4d2021-10-28 00:07:29 +000041 Endpoint::ProcessPacket(packet_data, Packet::kServer));
Wyatt Heplerddfc0772021-09-03 16:46:25 -070042 Packet& packet = *result;
Alexei Frolov5d6d3922020-05-08 13:57:02 -070043
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070044 internal::rpc_lock().lock();
Wyatt Hepler1d000cc2021-10-20 11:05:06 -070045 internal::ServerCall* const call =
46 static_cast<internal::ServerCall*>(FindCall(packet));
47
Wyatt Hepler3aab7f62021-10-05 16:14:51 -070048 // Verbose log for debugging.
49 // PW_LOG_DEBUG("RPC server received packet type %u for %u:%08x/%08x",
50 // static_cast<unsigned>(packet.type()),
51 // static_cast<unsigned>(packet.channel_id()),
52 // static_cast<unsigned>(packet.service_id()),
53 // static_cast<unsigned>(packet.method_id()));
54
Wyatt Heplerddfc0772021-09-03 16:46:25 -070055 internal::Channel* channel = GetInternalChannel(packet.channel_id());
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070056
Alexei Frolov5d6d3922020-05-08 13:57:02 -070057 if (channel == nullptr) {
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070058 // If the requested channel doesn't exist, try to dynamically assign one.
59 channel = AssignChannel(packet.channel_id(), interface);
60 if (channel == nullptr) {
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070061 internal::rpc_lock().unlock();
Wyatt Hepler3be460d2021-09-09 16:28:12 -070062 // If a channel can't be assigned, send a RESOURCE_EXHAUSTED error. Never
63 // send responses to error messages, though, to avoid infinite cycles.
64 if (packet.type() != PacketType::CLIENT_ERROR) {
65 internal::Channel temp_channel(packet.channel_id(), &interface);
66 temp_channel
67 .Send(Packet::ServerError(packet, Status::ResourceExhausted()))
68 .IgnoreError();
69 }
70 return OkStatus(); // OK since the packet was handled
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070071 }
Alexei Frolov5d6d3922020-05-08 13:57:02 -070072 }
73
Wyatt Hepler0f262352020-07-29 09:51:27 -070074 const auto [service, method] = FindMethod(packet);
75
76 if (method == nullptr) {
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070077 internal::rpc_lock().unlock();
Wyatt Hepler3be460d2021-09-09 16:28:12 -070078 // Don't send responses to errors to avoid infinite error cycles.
79 if (packet.type() != PacketType::CLIENT_ERROR) {
80 channel->Send(Packet::ServerError(packet, Status::NotFound()))
81 .IgnoreError();
82 }
83 return OkStatus(); // OK since the packet was handled.
Wyatt Hepler0f262352020-07-29 09:51:27 -070084 }
85
86 switch (packet.type()) {
87 case PacketType::REQUEST: {
Wyatt Hepler960f5df2021-09-08 10:17:21 -070088 // If the REQUEST is for an ongoing RPC, the existing call will be
89 // cancelled when the new call object is created.
Alexei Frolov86e05de2021-10-19 16:52:31 -070090 const internal::CallContext context(
91 *this, *channel, *service, *method, packet.call_id());
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070092 internal::rpc_lock().unlock();
Wyatt Heplerddfc0772021-09-03 16:46:25 -070093 method->Invoke(context, packet);
Wyatt Hepler0f262352020-07-29 09:51:27 -070094 break;
95 }
Wyatt Heplera9211162021-06-12 15:40:11 -070096 case PacketType::CLIENT_STREAM:
Wyatt Heplerddfc0772021-09-03 16:46:25 -070097 HandleClientStreamPacket(packet, *channel, call);
Wyatt Hepler0f262352020-07-29 09:51:27 -070098 break;
99 case PacketType::CLIENT_ERROR:
Wyatt Hepler17169152021-10-20 18:46:08 -0700100 case PacketType::DEPRECATED_CANCEL:
Alexei Frolov86e05de2021-10-19 16:52:31 -0700101 if (call != nullptr && call->id() == packet.call_id()) {
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700102 call->HandleError(packet.status());
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -0700103 } else {
104 internal::rpc_lock().unlock();
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700105 }
Wyatt Hepler0f262352020-07-29 09:51:27 -0700106 break;
Wyatt Heplera9211162021-06-12 15:40:11 -0700107 case PacketType::CLIENT_STREAM_END:
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700108 HandleClientStreamPacket(packet, *channel, call);
Wyatt Heplera9211162021-06-12 15:40:11 -0700109 break;
Wyatt Hepler0f262352020-07-29 09:51:27 -0700110 default:
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -0700111 internal::rpc_lock().unlock();
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700112 PW_LOG_WARN("pw_rpc server unable to handle packet of type %u",
Wyatt Hepler0f262352020-07-29 09:51:27 -0700113 unsigned(packet.type()));
114 }
Wyatt Hepler1d000cc2021-10-20 11:05:06 -0700115
116 return OkStatus(); // OK since the packet was handled
Wyatt Hepler0f262352020-07-29 09:51:27 -0700117}
118
Wyatt Heplercbd09c22020-09-15 11:17:24 -0700119std::tuple<Service*, const internal::Method*> Server::FindMethod(
Wyatt Hepler0f262352020-07-29 09:51:27 -0700120 const internal::Packet& packet) {
Wyatt Hepler712d3672020-07-13 15:52:11 -0700121 // Packets always include service and method IDs.
Wyatt Hepler3e2d7192020-06-11 08:28:21 -0700122 auto service = std::find_if(services_.begin(), services_.end(), [&](auto& s) {
Wyatt Hepler712d3672020-07-13 15:52:11 -0700123 return s.id() == packet.service_id();
Wyatt Hepler3e2d7192020-06-11 08:28:21 -0700124 });
125
126 if (service == services_.end()) {
Wyatt Hepler0f262352020-07-29 09:51:27 -0700127 return {};
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700128 }
129
Wyatt Hepler0f262352020-07-29 09:51:27 -0700130 return {&(*service), service->FindMethod(packet.method_id())};
Wyatt Hepler712d3672020-07-13 15:52:11 -0700131}
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700132
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700133void Server::HandleClientStreamPacket(const internal::Packet& packet,
134 internal::Channel& channel,
Wyatt Hepler960f5df2021-09-08 10:17:21 -0700135 internal::ServerCall* call) const {
Alexei Frolov86e05de2021-10-19 16:52:31 -0700136 if (call == nullptr || call->id() != packet.call_id()) {
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -0700137 internal::rpc_lock().unlock();
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700138 PW_LOG_DEBUG(
Wyatt Hepler3aab7f62021-10-05 16:14:51 -0700139 "Received client stream packet for %u:%08x/%08x, which is not pending",
140 static_cast<unsigned>(packet.channel_id()),
141 static_cast<unsigned>(packet.service_id()),
142 static_cast<unsigned>(packet.method_id()));
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000143 channel.Send(Packet::ServerError(packet, Status::FailedPrecondition()))
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700144 .IgnoreError(); // Errors are logged in Channel::Send.
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700145 return;
146 }
147
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700148 if (!call->has_client_stream()) {
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -0700149 internal::rpc_lock().unlock();
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000150 channel.Send(Packet::ServerError(packet, Status::InvalidArgument()))
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700151 .IgnoreError(); // Errors are logged in Channel::Send.
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700152 return;
153 }
154
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700155 if (!call->client_stream_open()) {
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -0700156 internal::rpc_lock().unlock();
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000157 channel.Send(Packet::ServerError(packet, Status::FailedPrecondition()))
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700158 .IgnoreError(); // Errors are logged in Channel::Send.
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700159 return;
160 }
161
162 if (packet.type() == PacketType::CLIENT_STREAM) {
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700163 call->HandlePayload(packet.payload());
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700164 } else { // Handle PacketType::CLIENT_STREAM_END.
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -0700165 call->HandleClientStreamEnd();
Wyatt Hepler712d3672020-07-13 15:52:11 -0700166 }
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700167}
168
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700169} // namespace pw::rpc