// Copyright 2021 The ChromiumOS Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef VM_TOOLS_SOMMELIER_SOMMELIER_UTIL_H_ #define VM_TOOLS_SOMMELIER_SOMMELIER_UTIL_H_ #include #include #include #include #include #include #define errno_assert(rv) \ { \ int macro_private_assert_value = (rv); \ if (!macro_private_assert_value) { \ fprintf(stderr, "Unexpected error: %s\n", strerror(errno)); \ assert(false); \ } \ } #define UNUSED(x) ((void)(x)) // Performs an asprintf operation and checks the result for validity and calls // abort() if there's a failure. Returns a newly allocated string rather than // taking a double pointer argument like asprintf. __attribute__((__format__(__printf__, 1, 0))) char* sl_xasprintf( const char* fmt, ...); #define DEFAULT_DELETER_FDECL(TypeName) \ namespace std { \ template <> \ struct default_delete { \ void operator()(TypeName* ptr); \ }; \ } DEFAULT_DELETER_FDECL(struct wl_event_source); // Maps wl_ to sl_ types, e.g. WlToSl::type == sl_host_seat. template struct WlToSl; #define MAP_STRUCTS(WlType, SlType) \ template <> \ struct WlToSl { \ using type = SlType; \ }; // Convert a request argument of type InArg to type OutArg. InArg is the type // sommelier receives as a Wayland host. OutArg is the type used passed to the // real host compositor. For Wayland resources, these will be wl_resource* and // wl_..* (e.g. wl_surface*) respectively. template struct ConvertRequestArg {}; template <> struct ConvertRequestArg { inline static const char* Convert(const char* arg) { return arg; } }; template <> struct ConvertRequestArg { inline static uint32_t Convert(uint32_t arg) { return arg; } }; template <> struct ConvertRequestArg { inline static int32_t Convert(int32_t arg) { return arg; } }; template struct ConvertRequestArg { static OutArg* Convert(wl_resource* resource) { if (!resource) return nullptr; using SlType = typename WlToSl::type; SlType* host = static_cast(wl_resource_get_user_data(resource)); return host ? host->proxy : nullptr; } }; template inline bool IsNullWlResource(T arg) { return false; } template <> inline bool IsNullWlResource(wl_resource* resource) { return resource == nullptr; } enum class AllowNullResource { kNo = 0, kYes = 1, }; // Invoke the given wl_ function with each arg converted. This helper struct is // so we can extract types from the wl_ function into a parameter pack for the // fold expression and not require them to be explicitly written out. template struct ForwardRequestHelper; template struct ForwardRequestHelper { template static void Forward(struct wl_client* client, InArgs... args) { if (allow_null == AllowNullResource::kNo) { if ((IsNullWlResource(args) || ...)) { fprintf(stderr, "error: received unexpected null resource in: %s\n", __PRETTY_FUNCTION__); return; } } wl_function(ConvertRequestArg::Convert(args)...); } }; // Wraps the function which dispatches an request to the host for use as // implementation for sommelier's implementation as a host. If null Wayland // resources should be allowed, AllowNullResource::kYes should be set, // otherwise the request will be considered invalid and dropped. // Example usage: // - ForwardRequest, // - ForwardRequest // // The first argument (receiving object) is guaranteed by Wayland to be // non-null but for code simplicity it is handled the same as the request // arguments, with null being allowed or disallowed based on |allow_null|. template void ForwardRequest(InArgs... args) { ForwardRequestHelper::template Forward( args...); } #endif // VM_TOOLS_SOMMELIER_SOMMELIER_UTIL_H_