Wyatt Hepler | 948f547 | 2020-06-02 16:52:28 -0700 | [diff] [blame] | 1 | // 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 Hepler | 8ec2cf8 | 2021-07-09 17:18:41 -0700 | [diff] [blame] | 15 | #include "pw_rpc/nanopb/internal/method.h" |
Wyatt Hepler | 948f547 | 2020-06-02 16:52:28 -0700 | [diff] [blame] | 16 | |
| 17 | #include "pb_decode.h" |
| 18 | #include "pb_encode.h" |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 19 | #include "pw_log/log.h" |
| 20 | #include "pw_rpc/internal/packet.h" |
Wyatt Hepler | 948f547 | 2020-06-02 16:52:28 -0700 | [diff] [blame] | 21 | |
Wyatt Hepler | 01fc15b | 2021-06-10 18:15:59 -0700 | [diff] [blame] | 22 | namespace pw::rpc { |
Wyatt Hepler | 948f547 | 2020-06-02 16:52:28 -0700 | [diff] [blame] | 23 | |
| 24 | using std::byte; |
| 25 | |
Wyatt Hepler | 01fc15b | 2021-06-10 18:15:59 -0700 | [diff] [blame] | 26 | namespace internal { |
| 27 | |
Wyatt Hepler | 29332d9 | 2021-09-02 07:49:53 -0700 | [diff] [blame] | 28 | void NanopbMethod::CallSynchronousUnary(CallContext& call, |
Wyatt Hepler | 59b37f7 | 2021-06-15 16:23:44 -0700 | [diff] [blame] | 29 | const Packet& request, |
| 30 | void* request_struct, |
| 31 | void* response_struct) const { |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 32 | if (!DecodeRequest(call.channel(), request, request_struct)) { |
| 33 | return; |
Wyatt Hepler | 948f547 | 2020-06-02 16:52:28 -0700 | [diff] [blame] | 34 | } |
| 35 | |
Wyatt Hepler | 59b37f7 | 2021-06-15 16:23:44 -0700 | [diff] [blame] | 36 | const Status status = |
| 37 | function_.synchronous_unary(call, request_struct, response_struct); |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 38 | SendResponse(call.channel(), request, response_struct, status); |
Wyatt Hepler | 948f547 | 2020-06-02 16:52:28 -0700 | [diff] [blame] | 39 | } |
| 40 | |
Wyatt Hepler | 29332d9 | 2021-09-02 07:49:53 -0700 | [diff] [blame] | 41 | void NanopbMethod::CallUnaryRequest(CallContext& call, |
Wyatt Hepler | fa6edcc | 2021-08-20 08:30:08 -0700 | [diff] [blame] | 42 | MethodType type, |
Wyatt Hepler | 59b37f7 | 2021-06-15 16:23:44 -0700 | [diff] [blame] | 43 | const Packet& request, |
| 44 | void* request_struct) const { |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 45 | if (!DecodeRequest(call.channel(), request, request_struct)) { |
| 46 | return; |
Wyatt Hepler | 948f547 | 2020-06-02 16:52:28 -0700 | [diff] [blame] | 47 | } |
| 48 | |
Wyatt Hepler | fa6edcc | 2021-08-20 08:30:08 -0700 | [diff] [blame] | 49 | GenericNanopbResponder server_writer(call, type); |
Wyatt Hepler | 59b37f7 | 2021-06-15 16:23:44 -0700 | [diff] [blame] | 50 | function_.unary_request(call, request_struct, server_writer); |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 51 | } |
| 52 | |
Wyatt Hepler | cbd09c2 | 2020-09-15 11:17:24 -0700 | [diff] [blame] | 53 | bool NanopbMethod::DecodeRequest(Channel& channel, |
| 54 | const Packet& request, |
| 55 | void* proto_struct) const { |
Wyatt Hepler | 59b37f7 | 2021-06-15 16:23:44 -0700 | [diff] [blame] | 56 | if (serde_.DecodeRequest(request.payload(), proto_struct)) { |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 57 | return true; |
| 58 | } |
| 59 | |
Wyatt Hepler | c2a520c | 2021-03-25 14:55:30 -0700 | [diff] [blame] | 60 | PW_LOG_WARN("Nanopb failed to decode request payload from channel %u", |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 61 | unsigned(channel.id())); |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 62 | channel.Send(Packet::ServerError(request, Status::DataLoss())); |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 63 | return false; |
| 64 | } |
| 65 | |
Wyatt Hepler | cbd09c2 | 2020-09-15 11:17:24 -0700 | [diff] [blame] | 66 | void NanopbMethod::SendResponse(Channel& channel, |
| 67 | const Packet& request, |
| 68 | const void* response_struct, |
| 69 | Status status) const { |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 70 | Channel::OutputBuffer response_buffer = channel.AcquireBuffer(); |
| 71 | std::span payload_buffer = response_buffer.payload(request); |
| 72 | |
Wyatt Hepler | 59b37f7 | 2021-06-15 16:23:44 -0700 | [diff] [blame] | 73 | StatusWithSize encoded = |
| 74 | serde_.EncodeResponse(response_struct, payload_buffer); |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 75 | |
| 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 Shmukler | c08854b | 2021-03-31 18:02:01 -0700 | [diff] [blame] | 81 | pw::Status send_status = channel.Send(response_buffer, response); |
| 82 | if (send_status.ok()) { |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 83 | return; |
| 84 | } |
Alexei Frolov | 514bab8 | 2021-01-22 13:14:38 -0800 | [diff] [blame] | 85 | |
Maksim Shmukler | c08854b | 2021-03-31 18:02:01 -0700 | [diff] [blame] | 86 | PW_LOG_WARN("Failed to send response packet for channel %u, status %u", |
| 87 | unsigned(channel.id()), |
| 88 | send_status.code()); |
| 89 | |
Alexei Frolov | 514bab8 | 2021-01-22 13:14:38 -0800 | [diff] [blame] | 90 | // Re-acquire the buffer to encode an error packet. |
| 91 | response_buffer = channel.AcquireBuffer(); |
Maksim Shmukler | c08854b | 2021-03-31 18:02:01 -0700 | [diff] [blame] | 92 | } else { |
Wyatt Hepler | c2a520c | 2021-03-25 14:55:30 -0700 | [diff] [blame] | 93 | PW_LOG_WARN( |
| 94 | "Nanopb failed to encode response packet for channel %u, status %u", |
| 95 | unsigned(channel.id()), |
| 96 | encoded.status().code()); |
Wyatt Hepler | 712d367 | 2020-07-13 15:52:11 -0700 | [diff] [blame] | 97 | } |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 98 | channel.Send(response_buffer, |
| 99 | Packet::ServerError(request, Status::Internal())); |
Wyatt Hepler | 948f547 | 2020-06-02 16:52:28 -0700 | [diff] [blame] | 100 | } |
| 101 | |
Wyatt Hepler | 01fc15b | 2021-06-10 18:15:59 -0700 | [diff] [blame] | 102 | } // namespace internal |
| 103 | } // namespace pw::rpc |