blob: c91460c9e448407cf925aef029e0e0eb00a1d5d0 [file] [log] [blame]
// 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.
#pragma once
#include <limits.h>
#include <fbl/function.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/macros.h>
#include <fbl/mutex.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <fbl/string.h>
#include <fbl/string_buffer.h>
#include <fbl/string_piece.h>
#include <lib/zx/channel.h>
#include <zircon/types.h>
namespace fdio_internal {
using EnumerateCallback = fbl::Function<zx_status_t(const fbl::StringPiece& path,
const zx::channel& channel)>;
// Represents a mapping from a string name to a remote connection.
//
// Each LocalVnode may have named children, which themselves may also
// optionally represent remote connections.
//
// This class is thread-compatible.
class LocalVnode : public fbl::RefCounted<LocalVnode>,
public fbl::DoublyLinkedListable<fbl::RefPtr<LocalVnode>> {
public:
DISALLOW_COPY_ASSIGN_AND_MOVE(LocalVnode);
// Initializes a new vnode, and attaches a reference to it inside an
// (optional) parent.
static fbl::RefPtr<LocalVnode> Create(fbl::RefPtr<LocalVnode> parent,
zx::channel remote, fbl::String name);
// Recursively unlinks this Vnode's children, and detaches this node from
// its parent.
void Unlink();
// Sets the remote connection of the current vnode.
// This is only permitted if the current vnode has:
// - No existing connection, and
// - No children.
zx_status_t SetRemote(zx::channel remote);
// Invoke |Fn()| on all children of this LocalVnode.
// May be used as a const visitor-pattern for all children.
//
// Any status other than ZX_OK returned from |Fn()| will halt iteration
// immediately and return.
template <typename Fn>
zx_status_t ForAllChildren(Fn fn) const {
for (const LocalVnode& vn : children_) {
zx_status_t status = fn(vn);
if (status != ZX_OK) {
return status;
}
}
return ZX_OK;
}
// Returns a child if it has the name |name|.
// Otherwise, returns nullptr.
fbl::RefPtr<LocalVnode> Lookup(const fbl::StringPiece& name) const;
// Remote is "set-once". If it is valid, this class guarantees that
// the value of |Remote()| will not change for the lifetime of |LocalVnode|.
const zx::channel& Remote() const { return remote_; }
const fbl::String& Name() const { return name_; }
private:
using ChildList = fbl::DoublyLinkedList<fbl::RefPtr<LocalVnode>>;
LocalVnode(fbl::RefPtr<LocalVnode> parent, zx::channel remote, fbl::String name);
void UnlinkChildren();
void UnlinkFromParent();
ChildList children_;
fbl::RefPtr<LocalVnode> parent_;
zx::channel remote_;
const fbl::String name_;
};
// Invoke |func| on the (path, channel) pairs for all remotes contained within |vn|.
//
// The path supplied to |func| is the full prefix from |vn|.
zx_status_t EnumerateRemotes(const LocalVnode& vn, const EnumerateCallback& func);
} // namespace fdio_internal