blob: 129d6271da6a6c9095dd2a97a26975ddaafc1f01 [file] [log] [blame]
Wyatt Hepler948f5472020-06-02 16:52:28 -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 Hepler8ec2cf82021-07-09 17:18:41 -070015#include "pw_rpc/nanopb/internal/method.h"
Wyatt Hepler948f5472020-06-02 16:52:28 -070016
17#include "pb_decode.h"
18#include "pb_encode.h"
Wyatt Hepler712d3672020-07-13 15:52:11 -070019#include "pw_log/log.h"
20#include "pw_rpc/internal/packet.h"
Wyatt Hepler948f5472020-06-02 16:52:28 -070021
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070022namespace pw::rpc {
Wyatt Hepler948f5472020-06-02 16:52:28 -070023
24using std::byte;
25
Wyatt Hepler01fc15b2021-06-10 18:15:59 -070026namespace internal {
27
Wyatt Hepler29332d92021-09-02 07:49:53 -070028void NanopbMethod::CallSynchronousUnary(CallContext& call,
Wyatt Hepler59b37f72021-06-15 16:23:44 -070029 const Packet& request,
30 void* request_struct,
31 void* response_struct) const {
Wyatt Hepler712d3672020-07-13 15:52:11 -070032 if (!DecodeRequest(call.channel(), request, request_struct)) {
33 return;
Wyatt Hepler948f5472020-06-02 16:52:28 -070034 }
35
Wyatt Hepler59b37f72021-06-15 16:23:44 -070036 const Status status =
37 function_.synchronous_unary(call, request_struct, response_struct);
Wyatt Hepler712d3672020-07-13 15:52:11 -070038 SendResponse(call.channel(), request, response_struct, status);
Wyatt Hepler948f5472020-06-02 16:52:28 -070039}
40
Wyatt Hepler29332d92021-09-02 07:49:53 -070041void NanopbMethod::CallUnaryRequest(CallContext& call,
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -070042 MethodType type,
Wyatt Hepler59b37f72021-06-15 16:23:44 -070043 const Packet& request,
44 void* request_struct) const {
Wyatt Hepler712d3672020-07-13 15:52:11 -070045 if (!DecodeRequest(call.channel(), request, request_struct)) {
46 return;
Wyatt Hepler948f5472020-06-02 16:52:28 -070047 }
48
Wyatt Heplerfa6edcc2021-08-20 08:30:08 -070049 GenericNanopbResponder server_writer(call, type);
Wyatt Hepler59b37f72021-06-15 16:23:44 -070050 function_.unary_request(call, request_struct, server_writer);
Wyatt Hepler712d3672020-07-13 15:52:11 -070051}
52
Wyatt Heplercbd09c22020-09-15 11:17:24 -070053bool NanopbMethod::DecodeRequest(Channel& channel,
54 const Packet& request,
55 void* proto_struct) const {
Wyatt Hepler59b37f72021-06-15 16:23:44 -070056 if (serde_.DecodeRequest(request.payload(), proto_struct)) {
Wyatt Hepler712d3672020-07-13 15:52:11 -070057 return true;
58 }
59
Wyatt Heplerc2a520c2021-03-25 14:55:30 -070060 PW_LOG_WARN("Nanopb failed to decode request payload from channel %u",
Wyatt Hepler712d3672020-07-13 15:52:11 -070061 unsigned(channel.id()));
Wyatt Heplerd78f7c62020-09-28 14:27:32 -070062 channel.Send(Packet::ServerError(request, Status::DataLoss()));
Wyatt Hepler712d3672020-07-13 15:52:11 -070063 return false;
64}
65
Wyatt Heplercbd09c22020-09-15 11:17:24 -070066void NanopbMethod::SendResponse(Channel& channel,
67 const Packet& request,
68 const void* response_struct,
69 Status status) const {
Wyatt Hepler712d3672020-07-13 15:52:11 -070070 Channel::OutputBuffer response_buffer = channel.AcquireBuffer();
71 std::span payload_buffer = response_buffer.payload(request);
72
Wyatt Hepler59b37f72021-06-15 16:23:44 -070073 StatusWithSize encoded =
74 serde_.EncodeResponse(response_struct, payload_buffer);
Wyatt Hepler712d3672020-07-13 15:52:11 -070075
76 if (encoded.ok()) {
77 Packet response = Packet::Response(request);
78
79 response.set_payload(payload_buffer.first(encoded.size()));
80 response.set_status(status);
Maksim Shmuklerc08854b2021-03-31 18:02:01 -070081 pw::Status send_status = channel.Send(response_buffer, response);
82 if (send_status.ok()) {
Wyatt Hepler712d3672020-07-13 15:52:11 -070083 return;
84 }
Alexei Frolov514bab82021-01-22 13:14:38 -080085
Maksim Shmuklerc08854b2021-03-31 18:02:01 -070086 PW_LOG_WARN("Failed to send response packet for channel %u, status %u",
87 unsigned(channel.id()),
88 send_status.code());
89
Alexei Frolov514bab82021-01-22 13:14:38 -080090 // Re-acquire the buffer to encode an error packet.
91 response_buffer = channel.AcquireBuffer();
Maksim Shmuklerc08854b2021-03-31 18:02:01 -070092 } else {
Wyatt Heplerc2a520c2021-03-25 14:55:30 -070093 PW_LOG_WARN(
94 "Nanopb failed to encode response packet for channel %u, status %u",
95 unsigned(channel.id()),
96 encoded.status().code());
Wyatt Hepler712d3672020-07-13 15:52:11 -070097 }
Wyatt Heplerd78f7c62020-09-28 14:27:32 -070098 channel.Send(response_buffer,
99 Packet::ServerError(request, Status::Internal()));
Wyatt Hepler948f5472020-06-02 16:52:28 -0700100}
101
Wyatt Hepler01fc15b2021-06-10 18:15:59 -0700102} // namespace internal
103} // namespace pw::rpc