blob: a96a78fc726c6bd511eab33bab325b58aedb7b7a [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
15#include "pw_rpc/server.h"
16
Wyatt Hepler3e2d7192020-06-11 08:28:21 -070017#include <algorithm>
18
Alexei Frolov5d6d3922020-05-08 13:57:02 -070019#include "pw_log/log.h"
Wyatt Heplerddfc0772021-09-03 16:46:25 -070020#include "pw_rpc/internal/endpoint.h"
Alexei Frolov5d6d3922020-05-08 13:57:02 -070021#include "pw_rpc/internal/packet.h"
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070022#include "pw_rpc/server_context.h"
Alexei Frolov5d6d3922020-05-08 13:57:02 -070023
24namespace pw::rpc {
Wyatt Hepler712d3672020-07-13 15:52:11 -070025namespace {
Alexei Frolov5d6d3922020-05-08 13:57:02 -070026
Wyatt Hepler80f26ff2020-06-01 09:30:17 -070027using std::byte;
28
Alexei Frolov5d6d3922020-05-08 13:57:02 -070029using internal::Packet;
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070030using internal::PacketType;
Alexei Frolov5d6d3922020-05-08 13:57:02 -070031
Wyatt Hepler712d3672020-07-13 15:52:11 -070032} // namespace
33
Wyatt Hepler0f262352020-07-29 09:51:27 -070034Status Server::ProcessPacket(std::span<const byte> data,
35 ChannelOutput& interface) {
Wyatt Hepler960f5df2021-09-08 10:17:21 -070036 internal::Call* base;
37 Result<Packet> result = Endpoint::ProcessPacket(data, Packet::kServer, base);
38 internal::ServerCall* const call = static_cast<internal::ServerCall*>(base);
Wyatt Heplerddfc0772021-09-03 16:46:25 -070039
40 if (!result.ok()) {
41 return result.status();
Wyatt Hepler0f262352020-07-29 09:51:27 -070042 }
43
Wyatt Heplerddfc0772021-09-03 16:46:25 -070044 Packet& packet = *result;
Alexei Frolov5d6d3922020-05-08 13:57:02 -070045
Wyatt Hepler3aab7f62021-10-05 16:14:51 -070046 // Verbose log for debugging.
47 // PW_LOG_DEBUG("RPC server received packet type %u for %u:%08x/%08x",
48 // static_cast<unsigned>(packet.type()),
49 // static_cast<unsigned>(packet.channel_id()),
50 // static_cast<unsigned>(packet.service_id()),
51 // static_cast<unsigned>(packet.method_id()));
52
Wyatt Heplerddfc0772021-09-03 16:46:25 -070053 internal::Channel* channel = GetInternalChannel(packet.channel_id());
Alexei Frolov5d6d3922020-05-08 13:57:02 -070054 if (channel == nullptr) {
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070055 // If the requested channel doesn't exist, try to dynamically assign one.
56 channel = AssignChannel(packet.channel_id(), interface);
57 if (channel == nullptr) {
Wyatt Hepler3be460d2021-09-09 16:28:12 -070058 // If a channel can't be assigned, send a RESOURCE_EXHAUSTED error. Never
59 // send responses to error messages, though, to avoid infinite cycles.
60 if (packet.type() != PacketType::CLIENT_ERROR) {
61 internal::Channel temp_channel(packet.channel_id(), &interface);
62 temp_channel
63 .Send(Packet::ServerError(packet, Status::ResourceExhausted()))
64 .IgnoreError();
65 }
66 return OkStatus(); // OK since the packet was handled
Alexei Frolov33a1e8f2020-05-26 08:39:32 -070067 }
Alexei Frolov5d6d3922020-05-08 13:57:02 -070068 }
69
Wyatt Hepler0f262352020-07-29 09:51:27 -070070 const auto [service, method] = FindMethod(packet);
71
72 if (method == nullptr) {
Wyatt Hepler3be460d2021-09-09 16:28:12 -070073 // Don't send responses to errors to avoid infinite error cycles.
74 if (packet.type() != PacketType::CLIENT_ERROR) {
75 channel->Send(Packet::ServerError(packet, Status::NotFound()))
76 .IgnoreError();
77 }
78 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(
86 *this, *channel, *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:
Alexei Frolov86e05de2021-10-19 16:52:31 -070094 if (call != nullptr && call->id() == packet.call_id()) {
Wyatt Heplerddfc0772021-09-03 16:46:25 -070095 call->HandleError(packet.status());
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070096 }
Wyatt Hepler0f262352020-07-29 09:51:27 -070097 break;
Wyatt Heplera9211162021-06-12 15:40:11 -070098 case PacketType::CANCEL:
Wyatt Heplerddfc0772021-09-03 16:46:25 -070099 HandleCancelPacket(packet, *channel, call);
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 Hepler82db4b12021-09-23 09:10:12 -0700105 PW_LOG_WARN("pw_rpc server unable to handle packet of type %u",
Wyatt Hepler0f262352020-07-29 09:51:27 -0700106 unsigned(packet.type()));
107 }
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800108 return OkStatus();
Wyatt Hepler0f262352020-07-29 09:51:27 -0700109}
110
Wyatt Heplercbd09c22020-09-15 11:17:24 -0700111std::tuple<Service*, const internal::Method*> Server::FindMethod(
Wyatt Hepler0f262352020-07-29 09:51:27 -0700112 const internal::Packet& packet) {
Wyatt Hepler712d3672020-07-13 15:52:11 -0700113 // Packets always include service and method IDs.
Wyatt Hepler3e2d7192020-06-11 08:28:21 -0700114 auto service = std::find_if(services_.begin(), services_.end(), [&](auto& s) {
Wyatt Hepler712d3672020-07-13 15:52:11 -0700115 return s.id() == packet.service_id();
Wyatt Hepler3e2d7192020-06-11 08:28:21 -0700116 });
117
118 if (service == services_.end()) {
Wyatt Hepler0f262352020-07-29 09:51:27 -0700119 return {};
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700120 }
121
Wyatt Hepler0f262352020-07-29 09:51:27 -0700122 return {&(*service), service->FindMethod(packet.method_id())};
Wyatt Hepler712d3672020-07-13 15:52:11 -0700123}
Wyatt Hepler80f26ff2020-06-01 09:30:17 -0700124
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700125void Server::HandleClientStreamPacket(const internal::Packet& packet,
126 internal::Channel& channel,
Wyatt Hepler960f5df2021-09-08 10:17:21 -0700127 internal::ServerCall* call) const {
Alexei Frolov86e05de2021-10-19 16:52:31 -0700128 if (call == nullptr || call->id() != packet.call_id()) {
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700129 PW_LOG_DEBUG(
Wyatt Hepler3aab7f62021-10-05 16:14:51 -0700130 "Received client stream packet for %u:%08x/%08x, which is not pending",
131 static_cast<unsigned>(packet.channel_id()),
132 static_cast<unsigned>(packet.service_id()),
133 static_cast<unsigned>(packet.method_id()));
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000134 channel.Send(Packet::ServerError(packet, Status::FailedPrecondition()))
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700135 .IgnoreError(); // Errors are logged in Channel::Send.
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700136 return;
137 }
138
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700139 if (!call->has_client_stream()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000140 channel.Send(Packet::ServerError(packet, Status::InvalidArgument()))
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700141 .IgnoreError(); // Errors are logged in Channel::Send.
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700142 return;
143 }
144
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700145 if (!call->client_stream_open()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000146 channel.Send(Packet::ServerError(packet, Status::FailedPrecondition()))
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700147 .IgnoreError(); // Errors are logged in Channel::Send.
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700148 return;
149 }
150
151 if (packet.type() == PacketType::CLIENT_STREAM) {
Wyatt Hepler82db4b12021-09-23 09:10:12 -0700152 call->HandlePayload(packet.payload());
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700153 } else { // Handle PacketType::CLIENT_STREAM_END.
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700154 call->EndClientStream();
Wyatt Hepler712d3672020-07-13 15:52:11 -0700155 }
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700156}
157
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700158void Server::HandleCancelPacket(const Packet& packet,
159 internal::Channel& channel,
Wyatt Hepler960f5df2021-09-08 10:17:21 -0700160 internal::ServerCall* call) const {
Alexei Frolov86e05de2021-10-19 16:52:31 -0700161 if (call == nullptr || call->id() != packet.call_id()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000162 channel.Send(Packet::ServerError(packet, Status::FailedPrecondition()))
163 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700164 PW_LOG_DEBUG("Received CANCEL packet for method that is not pending");
165 } else {
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700166 call->HandleError(Status::Cancelled());
Alexei Frolov062ed182020-09-28 16:23:06 -0700167 }
168}
169
Alexei Frolov5d6d3922020-05-08 13:57:02 -0700170} // namespace pw::rpc