blob: c29643dec4a844369a12d429d45de319397691f9 [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.
#pragma once
#include <zircon/compiler.h>
#include <zircon/types.h>
#include <fdio/limits.h>
#include <assert.h>
#include <limits.h>
#include <stdint.h>
__BEGIN_CDECLS
// clang-format off
// Determines whether or not client-side code should
// send requests using the Remote IO protocol or the
// FIDL protocol.
// #define ZXRIO_FIDL
#define ZXRIO_HDR_SZ (__builtin_offsetof(zxrio_msg_t, data))
#define ZXRIO_ONE_HANDLE 0x00000100
#define ZXRIO_TWO_HANDLES 0x00000200
// Identifier that this is a FIDL message, not
// a ZXRIO message.
//
// The header is shared between the two formats.
#define ZXRIO_FIDL_ORD 0x80000000
// RIO Ordinals
#define ZXRIO_STATUS 0x00000000
#define ZXRIO_CLOSE 0x00000001
#define ZXRIO_CLONE (0x00000002 | ZXRIO_ONE_HANDLE)
#define ZXRIO_OPEN (0x00000003 | ZXRIO_ONE_HANDLE)
#define ZXRIO_MISC 0x00000004
#define ZXRIO_READ 0x00000005
#define ZXRIO_WRITE 0x00000006
#define ZXRIO_SEEK 0x00000007
#define ZXRIO_STAT 0x00000008
#define ZXRIO_READDIR 0x00000009
#define ZXRIO_IOCTL 0x0000000a
#define ZXRIO_IOCTL_1H (0x0000000a | ZXRIO_ONE_HANDLE)
#define ZXRIO_IOCTL_2H (0x0000000a | ZXRIO_TWO_HANDLES)
#define ZXRIO_UNLINK 0x0000000b
#define ZXRIO_READ_AT 0x0000000c
#define ZXRIO_WRITE_AT 0x0000000d
#define ZXRIO_TRUNCATE 0x0000000e
#define ZXRIO_RENAME (0x0000000f | ZXRIO_ONE_HANDLE)
#define ZXRIO_CONNECT 0x00000010
#define ZXRIO_BIND 0x00000011
#define ZXRIO_LISTEN 0x00000012
#define ZXRIO_GETSOCKNAME 0x00000013
#define ZXRIO_GETPEERNAME 0x00000014
#define ZXRIO_GETSOCKOPT 0x00000015
#define ZXRIO_SETSOCKOPT 0x00000016
#define ZXRIO_GETADDRINFO 0x00000017
#define ZXRIO_SETATTR 0x00000018
#define ZXRIO_SYNC 0x00000019
#define ZXRIO_LINK (0x0000001a | ZXRIO_ONE_HANDLE)
#define ZXRIO_MMAP 0x0000001b
#define ZXRIO_FCNTL 0x0000001c
#define ZXRIO_REWIND 0x0000001d
#define ZXRIO_NUM_OPS 30
// FIDL Ordinals
// Object
#define ZXFIDL_CLONE 0x80000001
#define ZXFIDL_CLOSE 0x80000002
#define ZXRIO_ON_OPEN 0x80000007
// Node
#define ZXFIDL_SYNC 0x81000001
#define ZXFIDL_STAT 0x81000002
#define ZXFIDL_SETATTR 0x81000003
#define ZXFIDL_IOCTL 0x81000004
// File
#define ZXFIDL_READ 0x82000001
#define ZXFIDL_READ_AT 0x82000002
#define ZXFIDL_WRITE 0x82000003
#define ZXFIDL_WRITE_AT 0x82000004
#define ZXFIDL_SEEK 0x82000005
#define ZXFIDL_TRUNCATE 0x82000006
#define ZXFIDL_GET_FLAGS 0x82000007
#define ZXFIDL_SET_FLAGS 0x82000008
#define ZXFIDL_GET_VMO 0x82000009
// Directory
#define ZXFIDL_OPEN 0x83000001
#define ZXFIDL_UNLINK 0x83000002
#define ZXFIDL_READDIR 0x83000003
#define ZXFIDL_REWIND 0x83000004
#define ZXFIDL_RENAME 0x83000006
#define ZXFIDL_LINK 0x83000007
#define FIDL_ROUNDUP(n, a) (((n) + ((a) - 1)) & ~((a) - 1))
#define FIDL_ALIGN(a) FIDL_ROUNDUP((a), FIDL_ALIGNMENT)
#define ZXRIO_FIDL_MSG(n) ((n) & ZXRIO_FIDL_ORD)
#define ZXRIO_OP(n) (n) // opcode
#define ZXRIO_HC(n) (((n) >> 8) & 3) // handle count
#define ZXRIO_OPNAME(n) ((n) & 0xFF) // opcode, "name" part only
#define ZXRIO_OPNAMES { \
"status", "close", "clone", "open", \
"misc", "read", "write", "seek", \
"stat", "readdir", "ioctl", "unlink", \
"read_at", "write_at", "truncate", "rename", \
"connect", "bind", "listen", "getsockname", \
"getpeername", "getsockopt", "setsockopt", "getaddrinfo", \
"setattr", "sync", "link", "mmap", "fcntl", "rewind", }
// dispatcher callback return code that there were no messages to read
#define ERR_DISPATCHER_NO_WORK ZX_ERR_SHOULD_WAIT
// indicates message handed off to another server
// used by rio remote handler for deferred reply pipe completion
#define ERR_DISPATCHER_INDIRECT ZX_ERR_NEXT
// indicates the callback is taking responsibility for the
// channel receiving incoming messages.
//
// Unlike ERR_DISPATCHER_INDIRECT, this callback is propagated
// through the zxrio_handlers.
#define ERR_DISPATCHER_ASYNC ZX_ERR_ASYNC
// indicates that this was a close message and that no further
// callbacks should be made to the dispatcher
#define ERR_DISPATCHER_DONE ZX_ERR_STOP
const char* fdio_opname(uint32_t op);
typedef struct zxrio_msg zxrio_msg_t;
// callback to process a zxrio_msg
// - on entry datalen indicates how much valid data is in msg.data[]
// - return value of ERR_DISPATCHER_{INDIRECT,ASYNC} indicates that the reply is
// being handled by the callback (forwarded to another server, sent later,
// etc, and no reply message should be sent).
// - WARNING: Once this callback returns, usage of |msg| is no longer
// valid. If a client transmits ERR_DISPATCHER_{INDIRECT,ASYNC}, and intends
// to respond asynchronously, they must copy the fields of |msg| they
// wish to use at a later point in time.
// - otherwise, the return value is treated as the status to send
// in the rpc response, and msg.len indicates how much valid data
// to send. On error return msg.len will be set to 0.
typedef zx_status_t (*zxrio_cb_t)(zxrio_msg_t* msg, void* cookie);
// a fdio_dispatcher_handler suitable for use with a fdio_dispatcher
zx_status_t zxrio_handler(zx_handle_t h, zxrio_cb_t cb, void* cookie);
// the underlying handling for regular rpc or for a synthetic close,
// called by zxrio_handler. handle_rpc() processes a single message
// from the provideded channel, returning a negative error value on
// error or 1 on clean shutdown (indicating no further callbacks
// should be made). handle_close() processes a "synthetic" close
// event (eg, channel was remotely closed), and neither function
// should be callaed again after handle_close().
zx_status_t zxrio_handle_rpc(zx_handle_t h, zxrio_msg_t* msg, zxrio_cb_t cb, void* cookie);
// Invokes the callback with a "fake" close message. Useful when the
// client abruptly closes a handle without an explicit close message;
// this function allows the server to react the same way as a "clean" close.
zx_status_t zxrio_handle_close(zxrio_cb_t cb, void* cookie);
// Transmits a response message |msg| back to the client on the peer end of |h|.
zx_status_t zxrio_write_response(zx_handle_t h, zx_status_t status, zxrio_msg_t* msg);
// OPEN and CLOSE messages, can be forwarded to another remoteio server,
// without any need to wait for a reply. The reply channel from the initial
// request is passed along to the new server.
// If the write to the server fails, an error reply is sent to the reply channel.
zx_status_t zxrio_txn_handoff(zx_handle_t server, zx_handle_t reply, zxrio_msg_t* msg);
// OPEN and CLONE ops do not return a reply
// Instead they receive a channel handle that they write their status
// and (if successful) type, extra data, and handles to.
static_assert(sizeof(zx_txid_t) == 4,
"If the size of txid changes to 8 bytes then reserved0 should be removed from zxrio_msg");
typedef struct {
uint32_t tag;
uint32_t reserved;
union {
struct {
zx_handle_t e;
} file;
struct {
zx_handle_t s;
} pipe;
struct {
zx_handle_t v;
uint64_t offset;
uint64_t length;
} vmofile;
struct {
zx_handle_t e;
} device;
struct {
zx_handle_t s;
} socket;
};
} zxrio_object_info_t;
#define ZXRIO_DESCRIBE_HDR_SZ (__builtin_offsetof(zxrio_describe_t, extra))
// A one-way message which may be emitted by the server without an
// accompanying request. Optionally used as a part of the Open handshake.
typedef struct {
zx_txid_t txid; // FIDL2 message header
uint32_t reserved0; // Padding
uint32_t flags;
uint32_t op;
zx_status_t status;
zxrio_object_info_t* extra_ptr;
zxrio_object_info_t extra;
} zxrio_describe_t;
struct zxrio_msg {
zx_txid_t txid; // FIDL2 message header
uint32_t reserved0;
uint32_t flags;
uint32_t op;
uint32_t datalen; // size of data[]
int32_t arg; // tx: argument, rx: return value
union {
int64_t off; // tx/rx: offset where needed
uint32_t mode; // tx: Open
uint32_t op; // tx: Ioctl
} arg2;
int32_t reserved1;
uint32_t hcount; // number of valid handles
zx_handle_t handle[4]; // up to 3 handles + reply channel handle
uint8_t data[FDIO_CHUNK_SIZE]; // payload
};
#define FDIO_MMAP_FLAG_READ (1u << 0)
#define FDIO_MMAP_FLAG_WRITE (1u << 1)
#define FDIO_MMAP_FLAG_EXEC (1u << 2)
#define FDIO_MMAP_FLAG_PRIVATE (1u << 16)
static_assert(FDIO_MMAP_FLAG_READ == ZX_VM_FLAG_PERM_READ, "Vmar / Mmap flags should be aligned");
static_assert(FDIO_MMAP_FLAG_WRITE == ZX_VM_FLAG_PERM_WRITE, "Vmar / Mmap flags should be aligned");
static_assert(FDIO_MMAP_FLAG_EXEC == ZX_VM_FLAG_PERM_EXECUTE, "Vmar / Mmap flags should be aligned");
typedef struct zxrio_mmap_data {
size_t offset;
uint64_t length;
int32_t flags;
} zxrio_mmap_data_t;
static_assert(FDIO_CHUNK_SIZE >= PATH_MAX, "FDIO_CHUNK_SIZE must be large enough to contain paths");
#define READDIR_CMD_NONE 0
#define READDIR_CMD_RESET 1
// - msg.datalen is the size of data sent or received and must be <= FDIO_CHUNK_SIZE
// - msg.arg is the return code on replies
// request--------------------------------------- response------------------------------
// op arg arg2 data arg2 data handle[]
// ----------- ---------- ------- -------------- ----------- --------------------------
// CLOSE 0 0 - 0 - -
// CLONE 0 0 - objtype - handle(s)
// OPEN flags mode <name> objtype - handle(s)
// READ maxread 0 - newoffset <bytes> -
// READ_AT maxread offset - 0 <bytes> -
// WRITE 0 0 <bytes> newoffset - -
// WRITE_AT 0 offset <bytes> 0 - -
// SEEK whence offset - offset - -
// STAT maxreply 0 - 0 <vnattr_t> -
// READDIR maxreply cmd - 0 <vndirent_t[]> -
// IOCTL out_len opcode <in_bytes> 0 <out_bytes> -
// UNLINK 0 0 <name> 0 - -
// TRUNCATE 0 offset - 0 - -
// RENAME 0 0 <name1>0<name2>0 0 - -
// CONNECT 0 0 <sockaddr> 0 - -
// BIND 0 0 <sockaddr> 0 - -
// LISTEN 0 0 <backlog> 0 - -
// GETSOCKNAME maxreply 0 - 0 <sockaddr> -
// GETPEERNAME maxreply 0 - 0 <sockaddr> -
// GETSOCKOPT maxreply 0 <sockopt> 0 <sockopt> -
// SETSOCKOPT 0 0 <sockopt> 0 <sockopt> -
// GETADDRINFO maxreply 0 <getaddrinfo> 0 <getaddrinfo> -
// SETATTR 0 0 <vnattr> 0 - -
// SYNC 0 0 0 0 - -
// LINK 0 0 <name1>0<name2>0 0 - -
// MMAP maxreply 0 mmap_data_msg 0 mmap_data_msg vmohandle
// FCNTL cmd flags 0 flags - -
//
// proposed:
//
// LSTAT maxreply 0 - 0 <vnattr_t> -
// MKDIR 0 0 <name> 0 - -
// SYMLINK namelen 0 <name><path> 0 - -
// READLINK maxreply 0 - 0 <path> -
// FLUSH 0 0 - 0 - -
//
// on response arg32 is always zx_status, and may be positive for read/write calls
__END_CDECLS