blob: e7d09a8c975ecd6a1c3b0853069feaa42f97ccf1 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_LEDGER_BIN_FIDL_HELPERS_MESSAGE_RELAY_H_
#define SRC_LEDGER_BIN_FIDL_HELPERS_MESSAGE_RELAY_H_
#include <lib/async/cpp/wait.h>
#include <lib/fit/function.h>
#include <lib/zx/channel.h>
#include <queue>
#include <vector>
#include "src/lib/callback/destruction_sentinel.h"
#include "src/lib/fxl/macros.h"
namespace ledger {
namespace fidl_helpers {
// Moves data-only (no handles) messages across an zx::channel. This is an
// abstract base class with overridables for message arrival and channel
// closure. Use MessageRelay if you prefer to set callbacks for those things.
//
// MessageRelayBase is not thread-safe. All methods calls must be serialized.
class MessageRelayBase {
public:
virtual ~MessageRelayBase();
// Sets the channel that the relay should use to move messages.
void SetChannel(zx::channel channel);
// Sends a message.
void SendMessage(std::vector<uint8_t> message);
// Closes the channel.
void CloseChannel();
// Returns whether the channel is closed.
bool IsClosed() const;
protected:
MessageRelayBase();
// Called when a message is received.
virtual void OnMessageReceived(std::vector<uint8_t> message) = 0;
// Called when the channel closes.
virtual void OnChannelClosed() = 0;
private:
// Tries to read messages from channel_ and waits for more.
void ReadChannelMessages(async_dispatcher_t* dispatcher, async::WaitBase* wait,
zx_status_t status, const zx_packet_signal_t* signal);
// Writes all the messages in messages_to_write_.
void WriteChannelMessages(async_dispatcher_t* dispatcher, async::WaitBase* wait,
zx_status_t status, const zx_packet_signal_t* signal);
zx::channel channel_;
async::WaitMethod<MessageRelayBase, &MessageRelayBase::ReadChannelMessages> read_wait_{this};
async::WaitMethod<MessageRelayBase, &MessageRelayBase::WriteChannelMessages> write_wait_{this};
std::queue<std::vector<uint8_t>> messages_to_write_;
callback::DestructionSentinel destruction_sentinel_;
};
// Moves data-only (no handles) messages across an zx::channel.
//
// MessageRelay is not thread-safe. All methods calls must be serialized.
class MessageRelay : public MessageRelayBase {
public:
MessageRelay();
~MessageRelay() override;
void SetMessageReceivedCallback(fit::function<void(std::vector<uint8_t>)> callback);
void SetChannelClosedCallback(fit::closure callback);
protected:
void OnMessageReceived(std::vector<uint8_t> message) override;
void OnChannelClosed() override;
private:
fit::function<void(std::vector<uint8_t>)> message_received_callback_;
fit::closure channel_closed_callback_;
FXL_DISALLOW_COPY_AND_ASSIGN(MessageRelay);
};
} // namespace fidl_helpers
} // namespace ledger
#endif // SRC_LEDGER_BIN_FIDL_HELPERS_MESSAGE_RELAY_H_