1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_HOST_LINUX_GDBUS_FD_LIST_H_
#define REMOTING_HOST_LINUX_GDBUS_FD_LIST_H_
#include <gio/gio.h>
#include <glib.h>
#include <cstdint>
#include <optional>
#include <vector>
#include "base/files/scoped_file.h"
#include "base/types/expected.h"
#include "remoting/host/base/loggable.h"
#include "remoting/host/linux/gvariant_ref.h"
#include "remoting/host/linux/gvariant_type.h"
#include "ui/base/glib/scoped_gobject.h"
namespace remoting {
class SparseFdList;
// A list of file descriptors that can be sent or received as part of a D-Bus
// method call.
class GDBusFdList {
public:
// A handle to a file descriptor stored in an file-descriptor list. Can be
// converted to and from a GVariantRef<"h">.
struct Handle {
std::int32_t index;
};
// Movable, not copyable.
GDBusFdList();
~GDBusFdList();
GDBusFdList(GDBusFdList&&);
GDBusFdList& operator=(GDBusFdList&&);
// Takes ownership of the provided file descriptor, stores it in the list, and
// returns the resulting handle.
Handle Insert(base::ScopedFD fd);
// Attempts to dup the provided file descriptor, leaving the caller with
// ownership of the original. If dup succeeds, stores the new descriptor and
// returns the resulting handle. Otherwise, returns the error message.
base::expected<Handle, Loggable> InsertDup(int fd);
// Get the file descriptor associated with the given handle, or nullopt if
// there is no such file descriptor in the list. The list retains ownership of
// the file descriptor.
std::optional<int> Get(Handle handle);
// Converts to a SparseFdList.
SparseFdList MakeSparse() &&;
// Creates a new GUnixFDList owning the contained file descriptors, leaving
// this empty.
ScopedGObject<GUnixFDList> IntoGUnixFDList() &&;
// Creates a new GDBusFDList by stealing the file descriptors from a
// GUnixFDList, leaving it empty.
static GDBusFdList StealFromGUnixFDList(GUnixFDList* fd_list);
private:
std::vector<int> fds_;
};
// A list of file descriptors that may not be contiguous. Allows extracting
// ownership of individual file descriptors, but can not be sent over D-Bus.
class SparseFdList {
public:
using Handle = GDBusFdList::Handle;
// Movable, not copyable.
SparseFdList();
~SparseFdList();
SparseFdList(SparseFdList&&);
SparseFdList& operator=(SparseFdList&&);
// Get the file descriptor associated with the given handle, or nullopt if
// there is no such fd in the list. The list retains ownership of the file
// descriptor.
std::optional<int> Get(Handle handle);
// Removes and returns the file descriptor associated with the given handle,
// or a null ScopedFD if there is no such fd in the list. (Test the return
// value with .is_valid() before use.) Ownership is transferred to the caller.
base::ScopedFD Extract(Handle handle);
private:
explicit SparseFdList(std::vector<int> fds);
std::vector<int> fds_;
friend class GDBusFdList;
};
template <>
struct gvariant::Mapping<GDBusFdList::Handle> {
static constexpr Type kType = "h";
static GVariantRef<kType> From(GDBusFdList::Handle value) {
return GVariantRef<kType>::TakeUnchecked(g_variant_new_handle(value.index));
}
static GDBusFdList::Handle Into(const GVariantRef<kType>& variant) {
return GDBusFdList::Handle{g_variant_get_handle(variant.raw())};
}
};
} // namespace remoting
#endif // REMOTING_HOST_LINUX_GDBUS_FD_LIST_H_
|