| // 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 |