// Copyright 2019 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.
library fuchsia.developer.remotecontrol;

using fuchsia.boot as boot;
using fuchsia.component as component;
using fuchsia.diagnostics as diagnostics;
using fuchsia.io as io;
using fuchsia.kernel as kernel;
using fuchsia.net as net;
using fuchsia.sys2 as sys2;
using zx;

const MAX_NUM_MATCHES uint16 = 250;
const MAX_CONNECT_MATCHES uint16 = 5;

type RebootType = strict enum {
    // Standard reboot.
    REBOOT = 1;
    // Reboots into recovery mode.
    RECOVERY = 2;
    // Reboots into the bootloader.
    BOOTLOADER = 3;
};

type TunnelError = strict enum {
    // Couldn't connect to the address to forward.
    CONNECT_FAILED = 1;
    // Something was wrong with the socket which was being tunneled to.
    SOCKET_FAILED = 2;
    // Something was wrong with the ForwardCallback which was passed.
    CALLBACK_ERROR = 3;
};

@discoverable
protocol RemoteControl {
    /// Returns the input.
    EchoString(struct {
        value string:255;
    }) -> (struct {
        response string:255;
    });

    /// Connects to the root [`fuchsia.sys2/RealmExplorer`] protocol.
    RootRealmExplorer(resource struct {
        server server_end:sys2.RealmExplorer;
    }) -> () error zx.Status;

    /// Connects to the root [`fuchsia.sys2/RealmQuery`] protocol.
    RootRealmQuery(resource struct {
        server server_end:sys2.RealmQuery;
    }) -> () error zx.Status;

    /// Connects to the root [`fuchsia.sys2/LifecycleController`] protocol.
    RootLifecycleController(resource struct {
        server server_end:sys2.LifecycleController;
    }) -> () error zx.Status;

    /// Connects to the root [`fuchsia.sys2/RouteValidator`] protocol.
    RootRouteValidator(resource struct {
        server server_end:sys2.RouteValidator;
    }) -> () error zx.Status;

    // Connects to the [`fuchsia.kernel/Stats`] protocol
    KernelStats(resource struct {
        server server_end:kernel.Stats;
    }) -> () error zx.Status;

    // Connects to the [`fuchsia.boot/Arguments`] protocol
    BootArguments(resource struct {
        server server_end:boot.Arguments;
    }) -> () error zx.Status;

    IdentifyHost() -> (struct {
        response IdentifyHostResponse;
    }) error IdentifyHostError;

    // Connects a channel to a service, given a selector and a channel iff the selector
    // matches exactly one service on the system.
    // If successful, returns information about the service connected to.
    @deprecated("Please use `ConnectCapability`")
    Connect(resource struct {
        selector diagnostics.Selector;
        service_chan zx.Handle:CHANNEL;
    }) -> (struct {
        match ServiceMatch;
    }) error ConnectError;

    // Connects a channel to a service, given a moniker and a channel iff the
    // component identified by the given moniker exposes a capability of the
    // requested name.
    ConnectCapability(resource struct {
        moniker string:component.MAX_MONIKER_LENGTH;
        capability_name component.name;
        server_chan zx.Handle:CHANNEL;
        flags io.OpenFlags;
    }) -> () error ConnectCapabilityError;

    // AddId adds an identifier that can be recovered from IdentifyHost in order
    // to match this peer against a list of possible source peers. Callers are
    // expected to pick IDs randomly across the ID space, and only to add new
    // IDs to help identify transport or physical layer topologies. ffx uses
    // this API to pair an RCS instance discovered on Overnet to a device that
    // was discovered over mdns, for example.
    AddId(struct {
        id uint64;
    }) -> ();

    // Add a new Overnet link to this RCS instance. The node visible at the end
    // of this link will host only the RemoteControl service. This method also
    // performs the function of `AddId`, which is the purpose of the `id`
    // argument.
    AddOvernetLink(resource struct {
        id uint64;
        socket zx.Handle:SOCKET;
    }) -> ();

    // Establishes a TCP connection to the given address and forwards traffic through the given
    // socket.
    ForwardTcp(resource struct {
        addr net.SocketAddress;
        socket zx.Handle:SOCKET;
    }) -> () error TunnelError;

    // Listens on a TCP port and forwards any incoming connections to newly-created sockets which
    // are passed back via the callback.
    ReverseTcp(resource struct {
        addr net.SocketAddress;
        client client_end:ForwardCallback;
    }) -> () error TunnelError;

    // Gets the current monotonic time in nanoseconds.
    GetTime() -> (struct {
        time int64;
    });
};

protocol ForwardCallback {
    Forward(resource struct {
        socket zx.Handle:SOCKET;
        addr net.SocketAddress;
    });
};
