blob: 5d1fff4c5d3c121c1d59de708100e925bf2986c1 [file] [log] [blame]
// Copyright 2020 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 LIB_ZXIO_EXTENSIONS_H_
#define LIB_ZXIO_EXTENSIONS_H_
#include <lib/zxio/ops.h>
#include <lib/zxio/zxio.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
// This header exposes an extension mechanism for clients to inject
// custom implementations of the |zxio_t| interface, for |fuchsia.io|
// node types which are not fully supported by zxio.
//
// Currently, these node types are:
// - |fuchsia.io/DatagramSocket|
// - |fuchsia.io/StreamSocket|
__BEGIN_CDECLS
typedef struct zxio_node zxio_node_t;
typedef struct zxio_extension_ops zxio_extension_ops_t;
// Initializes |node| with a generic |fuchsia.io/Node| protocol support,
// consuming |control| regardless of success or failure.
//
// If not null, |ops| specifies operations to override from the base node
// implementation. See |zxio_extension_ops_t|.
typedef zx_status_t (*zxio_node_init_t)(zxio_node_t* node, zx_handle_t control,
const zxio_extension_ops_t* ops);
// These are node types that zxio does not have full support for, and where an
// external library can inject the full implementation. By default, zxio provides
// support for the |fuchsia.io/Node| portion of the protocol.
//
// In the function arguments, |io| points to an uninitialized storage for the
// new zxio object. The first handle, |control| is always the client end
// of the FIDL channel used when opening a new node. The extra handles usually
// correspond to transport specific logic, and their names denote the expected
// object type.
//
// |node_init| is provided as a convenience if the client wishes to re-use the
// |fuchsia.io/Node| support in zxio. In that case, users will compose |zxio_node_t|
// in their custom |zxio_t| implementation, then call this function to populate
// the node implementation. Doing so also handles picking the fuchsia.io v1/v2
// implementation automatically.
typedef struct zxio_extensions {
zx_status_t (*datagram_socket_init)(zxio_storage_t* io, zx_handle_t control,
zx_handle_t eventpair, zxio_node_init_t node_init);
zx_status_t (*stream_socket_init)(zxio_storage_t* io, zx_handle_t control, zx_handle_t socket,
zxio_node_init_t node_init);
} zxio_extensions_t;
// Replaces the extensions table within a |io|. Note that extensions
// are inherited across opening/cloning, and defaults to nullptr.
void zxio_extensions_set(zxio_t* io, const zxio_extensions_t* extensions);
// If applicable, returns which function in |extensions| was used to
// initialize this |zxio_t|. Otherwise, returns 0.
uintptr_t zxio_extensions_get_init_function(const zxio_t* io);
// Building block composed by socket/datagram/etc.
// This is provided for convenience, since the custom transports are expected to
// be largely identical in handling |fuchsia.io/Node| operations.
typedef struct zxio_node {
zxio_t io;
uint64_t opaque[2];
} zxio_node_t;
// Apart from |close|, these functions extend the |zxio_node_t| with
// implementations of operations beyond the ones relevant to |fuchsia.io/Node|.
//
// TODO(fxbug.dev/45659): We eventually would want to plumb extension support for all
// non-Node methods.
typedef struct zxio_extension_ops {
// A hook to close any resources held by the custom transport before the
// node portion is invalidated as part of |zxio_close|.
//
// If this entry is |nullptr|, the default behavior is to do nothing for the
// custom part (i.e. treat them as pure data).
void (*close)(zxio_node_t* io);
// Specifies whether running |zxio_close| on this node should call
// |fuchsia.io/Node.Close| and block.
// If true, the node will not call the FIDL |Close| method.
//
// If a |zxio_extension_ops_t| was not specified when initializing the node,
// the default behavior is to call |Close| and block.
bool skip_close_call;
// The default behavior is returning |ZX_ERR_NOT_SUPPORTED|.
zx_status_t (*readv)(zxio_node_t* io, const zx_iovec_t* vector, size_t vector_count,
zxio_flags_t flags, size_t* out_actual);
// The default behavior is returning |ZX_ERR_NOT_SUPPORTED|.
zx_status_t (*writev)(zxio_node_t* io, const zx_iovec_t* vector, size_t vector_count,
zxio_flags_t flags, size_t* out_actual);
} zxio_extension_ops_t;
zx_handle_t zxio_node_borrow_channel(const zxio_node_t* node);
__END_CDECLS
#endif // LIB_ZXIO_EXTENSIONS_H_