blob: 9982ff9464b26159b17fe2106caa3d43ff94322e [file] [log] [blame]
Wyatt Heplerddfc0772021-09-03 16:46:25 -07001// Copyright 2021 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
Wyatt Heplerddfc0772021-09-03 16:46:25 -070018#include "pw_rpc/internal/endpoint.h"
Ewout van Bekkum7f5b3052021-11-11 17:35:23 -080019// clang-format on
Wyatt Heplerddfc0772021-09-03 16:46:25 -070020
21#include "pw_log/log.h"
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070022#include "pw_rpc/internal/lock.h"
Wyatt Heplerddfc0772021-09-03 16:46:25 -070023
24namespace pw::rpc::internal {
25
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070026RpcLock& rpc_lock() {
27 static RpcLock lock;
28 return lock;
29}
30
Wyatt Heplerddfc0772021-09-03 16:46:25 -070031Endpoint::~Endpoint() {
32 // Since the calls remove themselves from the Endpoint in
33 // CloseAndSendResponse(), close responders until no responders remain.
34 while (!calls_.empty()) {
35 calls_.front().CloseAndSendResponse(OkStatus()).IgnoreError();
36 }
37}
38
39Result<Packet> Endpoint::ProcessPacket(std::span<const std::byte> data,
Wyatt Hepler1d000cc2021-10-20 11:05:06 -070040 Packet::Destination destination) {
Wyatt Heplerddfc0772021-09-03 16:46:25 -070041 Result<Packet> result = Packet::FromBuffer(data);
42
43 if (!result.ok()) {
44 PW_LOG_WARN("Failed to decode pw_rpc packet");
45 return Status::DataLoss();
46 }
47
48 Packet& packet = *result;
49
50 if (packet.channel_id() == Channel::kUnassignedChannelId ||
51 packet.service_id() == 0 || packet.method_id() == 0) {
52 PW_LOG_WARN("Received malformed pw_rpc packet");
53 return Status::DataLoss();
54 }
55
56 if (packet.destination() != destination) {
57 return Status::InvalidArgument();
58 }
59
Wyatt Heplerddfc0772021-09-03 16:46:25 -070060 return result;
61}
62
Wyatt Hepler960f5df2021-09-08 10:17:21 -070063void Endpoint::RegisterCall(Call& call) {
Wyatt Hepler16edd402022-01-06 17:25:39 -080064 rpc_lock().lock();
Wyatt Heplerc8bdc7d2021-10-20 09:29:01 -070065
Wyatt Heplerb1c47992022-01-06 11:05:50 -080066 Call* const existing_call = FindCallById(
67 call.channel_id_locked(), call.service_id(), call.method_id());
Wyatt Hepler960f5df2021-09-08 10:17:21 -070068
Wyatt Hepler960f5df2021-09-08 10:17:21 -070069 RegisterUniqueCall(call);
Wyatt Heplera06939d2022-01-06 09:55:18 -080070
71 if (existing_call != nullptr) {
72 existing_call->ReplaceWithNewInstance(call);
73 } else {
74 rpc_lock().unlock();
75 }
Wyatt Heplerddfc0772021-09-03 16:46:25 -070076}
77
78Channel* Endpoint::GetInternalChannel(uint32_t id) const {
79 for (Channel& c : channels_) {
80 if (c.id() == id) {
81 return &c;
82 }
83 }
84 return nullptr;
85}
86
87Channel* Endpoint::AssignChannel(uint32_t id, ChannelOutput& interface) {
88 internal::Channel* channel =
89 GetInternalChannel(Channel::kUnassignedChannelId);
90 if (channel == nullptr) {
91 return nullptr;
92 }
93
94 *channel = Channel(id, &interface);
95 return channel;
96}
97
Wyatt Hepler960f5df2021-09-08 10:17:21 -070098Call* Endpoint::FindCallById(uint32_t channel_id,
99 uint32_t service_id,
100 uint32_t method_id) {
101 for (Call& call : calls_) {
Wyatt Heplerb1c47992022-01-06 11:05:50 -0800102 if (channel_id == call.channel_id_locked() &&
103 service_id == call.service_id() && method_id == call.method_id()) {
Wyatt Hepler960f5df2021-09-08 10:17:21 -0700104 return &call;
105 }
106 }
107 return nullptr;
108}
109
Wyatt Heplerddfc0772021-09-03 16:46:25 -0700110} // namespace pw::rpc::internal