xref: /aosp_15_r20/external/pigweed/pw_rpc/channel.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2020 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker // clang-format off
16*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/log_config.h"  // PW_LOG_* macros must be first.
17*61c4878aSAndroid Build Coastguard Worker 
18*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/channel.h"
19*61c4878aSAndroid Build Coastguard Worker // clang-format on
20*61c4878aSAndroid Build Coastguard Worker 
21*61c4878aSAndroid Build Coastguard Worker #include "pw_assert/check.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/span.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_log/log.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/decoder.h"
25*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/find.h"
26*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/config.h"
27*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/encoding_buffer.h"
28*61c4878aSAndroid Build Coastguard Worker #include "pw_rpc/internal/packet.pwpb.h"
29*61c4878aSAndroid Build Coastguard Worker 
30*61c4878aSAndroid Build Coastguard Worker using pw::rpc::internal::pwpb::RpcPacket::Fields;
31*61c4878aSAndroid Build Coastguard Worker 
32*61c4878aSAndroid Build Coastguard Worker namespace pw::rpc {
33*61c4878aSAndroid Build Coastguard Worker namespace internal {
34*61c4878aSAndroid Build Coastguard Worker 
OverwriteChannelId(ByteSpan rpc_packet,uint32_t channel_id_under_128)35*61c4878aSAndroid Build Coastguard Worker Status OverwriteChannelId(ByteSpan rpc_packet, uint32_t channel_id_under_128) {
36*61c4878aSAndroid Build Coastguard Worker   Result<ConstByteSpan> raw_field =
37*61c4878aSAndroid Build Coastguard Worker       protobuf::FindRaw(rpc_packet, Fields::kChannelId);
38*61c4878aSAndroid Build Coastguard Worker   if (!raw_field.ok()) {
39*61c4878aSAndroid Build Coastguard Worker     return Status::DataLoss();  // Unexpected packet format
40*61c4878aSAndroid Build Coastguard Worker   }
41*61c4878aSAndroid Build Coastguard Worker   if (raw_field->size() != 1u) {
42*61c4878aSAndroid Build Coastguard Worker     return Status::OutOfRange();
43*61c4878aSAndroid Build Coastguard Worker   }
44*61c4878aSAndroid Build Coastguard Worker   const_cast<std::byte*>(raw_field->data())[0] =
45*61c4878aSAndroid Build Coastguard Worker       static_cast<std::byte>(channel_id_under_128);
46*61c4878aSAndroid Build Coastguard Worker   return OkStatus();
47*61c4878aSAndroid Build Coastguard Worker }
48*61c4878aSAndroid Build Coastguard Worker 
Send(const Packet & packet)49*61c4878aSAndroid Build Coastguard Worker Status ChannelBase::Send(const Packet& packet) {
50*61c4878aSAndroid Build Coastguard Worker   static constexpr bool kLogAllOutgoingPackets = false;
51*61c4878aSAndroid Build Coastguard Worker   if constexpr (kLogAllOutgoingPackets) {
52*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("pw_rpc channel sending RPC packet type %u for %u:%08x/%08x",
53*61c4878aSAndroid Build Coastguard Worker                 static_cast<unsigned>(packet.type()),
54*61c4878aSAndroid Build Coastguard Worker                 static_cast<unsigned>(packet.channel_id()),
55*61c4878aSAndroid Build Coastguard Worker                 static_cast<unsigned>(packet.service_id()),
56*61c4878aSAndroid Build Coastguard Worker                 static_cast<unsigned>(packet.method_id()));
57*61c4878aSAndroid Build Coastguard Worker   }
58*61c4878aSAndroid Build Coastguard Worker 
59*61c4878aSAndroid Build Coastguard Worker   ByteSpan buffer = encoding_buffer.GetPacketBuffer(packet.payload().size());
60*61c4878aSAndroid Build Coastguard Worker   Result encoded = packet.Encode(buffer);
61*61c4878aSAndroid Build Coastguard Worker 
62*61c4878aSAndroid Build Coastguard Worker   if (!encoded.ok()) {
63*61c4878aSAndroid Build Coastguard Worker     encoding_buffer.Release();
64*61c4878aSAndroid Build Coastguard Worker     PW_LOG_ERROR(
65*61c4878aSAndroid Build Coastguard Worker         "Failed to encode RPC packet type %u to channel %u buffer, status %u",
66*61c4878aSAndroid Build Coastguard Worker         static_cast<unsigned>(packet.type()),
67*61c4878aSAndroid Build Coastguard Worker         static_cast<unsigned>(id()),
68*61c4878aSAndroid Build Coastguard Worker         encoded.status().code());
69*61c4878aSAndroid Build Coastguard Worker     return Status::Internal();
70*61c4878aSAndroid Build Coastguard Worker   }
71*61c4878aSAndroid Build Coastguard Worker 
72*61c4878aSAndroid Build Coastguard Worker   PW_CHECK_NOTNULL(output_);
73*61c4878aSAndroid Build Coastguard Worker   Status sent = output_->Send(encoded.value());
74*61c4878aSAndroid Build Coastguard Worker   encoding_buffer.Release();
75*61c4878aSAndroid Build Coastguard Worker 
76*61c4878aSAndroid Build Coastguard Worker   if (!sent.ok()) {
77*61c4878aSAndroid Build Coastguard Worker     PW_LOG_DEBUG("Channel %u failed to send packet with status %u",
78*61c4878aSAndroid Build Coastguard Worker                  static_cast<unsigned>(id()),
79*61c4878aSAndroid Build Coastguard Worker                  sent.code());
80*61c4878aSAndroid Build Coastguard Worker 
81*61c4878aSAndroid Build Coastguard Worker     return Status::Unknown();
82*61c4878aSAndroid Build Coastguard Worker   }
83*61c4878aSAndroid Build Coastguard Worker   return OkStatus();
84*61c4878aSAndroid Build Coastguard Worker }
85*61c4878aSAndroid Build Coastguard Worker 
86*61c4878aSAndroid Build Coastguard Worker }  // namespace internal
87*61c4878aSAndroid Build Coastguard Worker 
ExtractChannelId(ConstByteSpan packet)88*61c4878aSAndroid Build Coastguard Worker Result<uint32_t> ExtractChannelId(ConstByteSpan packet) {
89*61c4878aSAndroid Build Coastguard Worker   protobuf::Decoder decoder(packet);
90*61c4878aSAndroid Build Coastguard Worker 
91*61c4878aSAndroid Build Coastguard Worker   while (decoder.Next().ok()) {
92*61c4878aSAndroid Build Coastguard Worker     if (static_cast<Fields>(decoder.FieldNumber()) != Fields::kChannelId) {
93*61c4878aSAndroid Build Coastguard Worker       continue;
94*61c4878aSAndroid Build Coastguard Worker     }
95*61c4878aSAndroid Build Coastguard Worker     uint32_t channel_id;
96*61c4878aSAndroid Build Coastguard Worker     PW_TRY(decoder.ReadUint32(&channel_id));
97*61c4878aSAndroid Build Coastguard Worker     return channel_id;
98*61c4878aSAndroid Build Coastguard Worker   }
99*61c4878aSAndroid Build Coastguard Worker 
100*61c4878aSAndroid Build Coastguard Worker   return Status::DataLoss();
101*61c4878aSAndroid Build Coastguard Worker }
102*61c4878aSAndroid Build Coastguard Worker 
103*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::rpc
104