blob: 24acafc71101af3e7d4340968d19c65ac42e4b31 [file] [log] [blame]
// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once
#include "pw_assert/light.h"
#include "pw_containers/intrusive_list.h"
#include "pw_rpc/internal/channel.h"
#include "pw_rpc/internal/packet.h"
#include "pw_status/status.h"
namespace pw::rpc::internal {
// Base class representing an active client-side RPC call. Implementations
// derive from this class and provide a packet handler function which is
// called with a reference to the ClientCall object and the received packet.
class BaseClientCall : public IntrusiveList<BaseClientCall>::Item {
public:
using ResponseHandler = void (*)(BaseClientCall&, const Packet&);
constexpr BaseClientCall(rpc::Channel* channel,
uint32_t service_id,
uint32_t method_id,
ResponseHandler handler)
: channel_(static_cast<Channel*>(channel)),
service_id_(service_id),
method_id_(method_id),
handler_(handler),
active_(true) {
PW_ASSERT(channel_ != nullptr);
Register();
}
~BaseClientCall() { Unregister(); }
BaseClientCall(const BaseClientCall&) = delete;
BaseClientCall& operator=(const BaseClientCall&) = delete;
BaseClientCall(BaseClientCall&& other) { *this = std::move(other); }
BaseClientCall& operator=(BaseClientCall&& other);
constexpr bool active() const { return active_; }
void Cancel();
protected:
constexpr Channel& channel() const { return *channel_; }
constexpr uint32_t service_id() const { return service_id_; }
constexpr uint32_t method_id() const { return method_id_; }
std::span<std::byte> AcquirePayloadBuffer();
Status ReleasePayloadBuffer(std::span<const std::byte> payload);
void Unregister();
private:
friend class rpc::Client;
void Register();
void HandleResponse(const Packet& packet) { handler_(*this, packet); }
Packet NewPacket(PacketType type,
std::span<const std::byte> payload = {}) const;
Channel* channel_;
uint32_t service_id_;
uint32_t method_id_;
Channel::OutputBuffer request_;
ResponseHandler handler_;
bool active_;
};
} // namespace pw::rpc::internal