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 #pragma once 15 16 #include "pw_assert/light.h" 17 #include "pw_containers/intrusive_list.h" 18 #include "pw_rpc/internal/channel.h" 19 #include "pw_rpc/internal/packet.h" 20 #include "pw_status/status.h" 21 22 namespace pw::rpc::internal { 23 24 // Base class representing an active client-side RPC call. Implementations 25 // derive from this class and provide a packet handler function which is 26 // called with a reference to the ClientCall object and the received packet. 27 class BaseClientCall : public IntrusiveList<BaseClientCall>::Item { 28 public: 29 using ResponseHandler = void (*)(BaseClientCall&, const Packet&); 30 BaseClientCall(rpc::Channel * channel,uint32_t service_id,uint32_t method_id,ResponseHandler handler)31 constexpr BaseClientCall(rpc::Channel* channel, 32 uint32_t service_id, 33 uint32_t method_id, 34 ResponseHandler handler) 35 : channel_(static_cast<Channel*>(channel)), 36 service_id_(service_id), 37 method_id_(method_id), 38 handler_(handler), 39 active_(true) { 40 PW_ASSERT(channel_ != nullptr); 41 Register(); 42 } 43 ~BaseClientCall()44 ~BaseClientCall() { Unregister(); } 45 46 BaseClientCall(const BaseClientCall&) = delete; 47 BaseClientCall& operator=(const BaseClientCall&) = delete; 48 BaseClientCall(BaseClientCall && other)49 BaseClientCall(BaseClientCall&& other) { *this = std::move(other); } 50 BaseClientCall& operator=(BaseClientCall&& other); 51 active()52 constexpr bool active() const { return active_; } 53 54 void Cancel(); 55 56 protected: channel()57 constexpr Channel& channel() const { return *channel_; } service_id()58 constexpr uint32_t service_id() const { return service_id_; } method_id()59 constexpr uint32_t method_id() const { return method_id_; } 60 61 std::span<std::byte> AcquirePayloadBuffer(); 62 Status ReleasePayloadBuffer(std::span<const std::byte> payload); 63 64 void Unregister(); 65 66 private: 67 friend class rpc::Client; 68 69 void Register(); 70 HandleResponse(const Packet & packet)71 void HandleResponse(const Packet& packet) { handler_(*this, packet); } 72 73 Packet NewPacket(PacketType type, 74 std::span<const std::byte> payload = {}) const; 75 76 Channel* channel_; 77 uint32_t service_id_; 78 uint32_t method_id_; 79 Channel::OutputBuffer request_; 80 ResponseHandler handler_; 81 bool active_; 82 }; 83 84 } // namespace pw::rpc::internal 85