blob: d3a079a5b2c27106166543fa61354680de8e98ad [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IPCZ_SRC_IPCZ_DRIVER_TRANSPORT_H_
#define IPCZ_SRC_IPCZ_DRIVER_TRANSPORT_H_
#include <cstddef>
#include <cstdint>
#include <utility>
#include <vector>
#include "ipcz/api_object.h"
#include "ipcz/driver_object.h"
#include "ipcz/ipcz.h"
#include "third_party/abseil-cpp/absl/base/macros.h"
#include "third_party/abseil-cpp/absl/types/span.h"
#include "util/ref_counted.h"
namespace ipcz {
class Message;
// Encapsulates shared ownership of a transport endpoint created by an ipcz
// driver. The driver calls into this object to notify ipcz of incoming messages
// on the transport, and ipcz calls into this object to submit outgoing messages
// for transmission by the driver.
class DriverTransport
: public APIObjectImpl<DriverTransport, APIObject::kTransportListener> {
public:
using Pair = std::pair<Ref<DriverTransport>, Ref<DriverTransport>>;
// A view into the unowned raw contents of an incoming transport message.
struct RawMessage {
absl::Span<const uint8_t> data;
absl::Span<const IpczDriverHandle> handles;
};
// A Listener to receive message and error events from the driver.
class Listener : public RefCounted<Listener> {
public:
// Accepts a raw message from the transport. Note that this is called
// without *any* validation of the size or content of `message`.
virtual bool OnTransportMessage(const RawMessage& message,
const DriverTransport& transport,
IpczDriverHandle envelope) = 0;
// Indicates that some unrecoverable error has occurred with the transport.
virtual void OnTransportError() = 0;
// Indicates that dectivation has been completed by the driver, meaning that
// no further methods will be invoked on this Listener.
virtual void OnTransportDeactivated() {}
protected:
friend class RefCounted<Listener>;
virtual ~Listener() = default;
};
// Constructs a new DriverTransport object over the driver-created transport
// handle in `transport`.
explicit DriverTransport(DriverObject transport);
// Creates a new pair of connected DriverTransports, one to send over
// `transport0`, and one to send over `transport1`, in order to establish a
// direct link between their respective remote nodes. Both `transport0` and
// `transport1` may be null if the new transport pair won't be sent anywhere.
static DriverTransport::Pair CreatePair(
const IpczDriver& driver,
const DriverTransport* transport0 = nullptr,
const DriverTransport* transport1 = nullptr);
// Set the object handling any incoming message or error notifications. This
// is only safe to set before Activate() is called, or from within one of the
// Listener methods when invoked by this DriverTransport (because invocations
// are mutually exclusive).
void set_listener(Ref<Listener> listener) { listener_ = std::move(listener); }
// Exposes the underlying driver handle for this transport.
const DriverObject& driver_object() const { return transport_; }
// Releases ownership of the underlying driver transport, returning it to the
// caller. After this call, the DriverTransport object is reset and
// `driver_object()` will return an invalid object.
DriverObject TakeDriverObject() {
ABSL_ASSERT(!listener_);
return std::move(transport_);
}
// Begins listening on the transport for incoming data and driver objects.
// Once this is called, the transport's Listener may be invoked by the driver
// at any time from arbitrary threads, as determined by the driver
// implementation itself. The driver will continue listening on this transport
// until Deactivate() is called or an unrecoverable error is encountered.
IpczResult Activate();
// Requests that the driver cease listening for incoming data and driver
// objects on this transport. Once a transport is deactivated, it can never be
// reactivated.
IpczResult Deactivate();
// Helper for transmitting macro-generated ipcz messages. This performs any
// necessary in-place serialization of driver objects before transmitting,
// hence it takes a mutable reference to `message`.
IpczResult Transmit(Message& message);
// Invoked by the driver any time this transport receives data and driver
// handles to be passed back into ipcz.
bool Notify(const RawMessage& message, IpczDriverHandle envelope);
void NotifyError();
// Invoked once the driver has finalized deactivation of this transport, as
// previously requested by a call to Deactivate().
void NotifyDeactivated();
// APIObject:
IpczResult Close() override;
private:
~DriverTransport() override;
DriverObject transport_;
Ref<Listener> listener_;
};
} // namespace ipcz
#endif // IPCZ_SRC_IPCZ_DRIVER_TRANSPORT_H_