Ctrl K
ComunidadGuías…

server/src/remote_session.h

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#pragma once

#include <chrono>
#include <cstdint>
#include <functional>
#include <mutex>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>

namespace remote_session {
  inline constexpr std::int32_t resume_id = 2147483501;
  inline constexpr std::int32_t disconnect_monitor_id = 2147483502;
  inline constexpr std::int32_t disconnect_input_id = 2147483503;
  // Keep this numeric identity stable so clients with a cached app tile keep
  // resolving the control after its user-facing name changes to Terminate.
  inline constexpr std::int32_t terminate_id = 2147483504;
  inline constexpr std::int32_t monitor_id = 2147483505;
  inline constexpr std::int32_t input_id = 2147483506;
  inline constexpr std::int32_t running_game_id = 2147483507;
  // Distinct identities prevent Moonlight from renaming cached primary tiles.
  inline constexpr std::int32_t secondary_resume_id = 2147483511;
  inline constexpr std::int32_t secondary_terminate_id = 2147483514;
  inline constexpr std::int32_t secondary_monitor_id = 2147483515;
  inline constexpr std::int32_t secondary_input_id = 2147483516;
  inline constexpr std::size_t max_client_vdds = 4;

  enum class role_e : std::uint8_t { none, input, monitor, game };
  enum class control_e : std::uint8_t { none, resume, disconnect_monitor, disconnect_input, terminate, monitor, input, running_game };
  enum class permission_e : std::uint8_t { view, launch, terminate };

  struct app_t {
    std::int32_t id {};
    std::string uuid;
    std::string title;
    bool synthetic {};
  };

  struct game_t {
    bool running {};
    std::string owner_uuid;
    std::uint64_t generation {};
    app_t app;
  };

  struct owner_t {
    role_e role {role_e::none};
    bool retained {};
    bool ready {};
    bool retryable {};
    std::optional<std::string> output;
  };

  struct caller_t {
    std::string uuid;
    bool paired {};
    bool may_view {};
    bool may_launch {};
    bool may_terminate {};
  };

  struct projection_t {
    bool free {true};
    std::int32_t current_game {};
    std::vector<app_t> catalogue;
  };

  struct dispatch_t {
    control_e control {control_e::none};
    permission_e permission {permission_e::view};
    role_e resume_role {role_e::none};
    bool allowed {};
    bool resume {};
    bool terminate {};
    bool already_complete {};
  };

  struct control_completion_t {
    int status_code {};
    std::string_view status_message;
  };

  enum class terminate_confirmation_e : std::uint8_t { prompt, confirmed };
  enum class app_replacement_confirmation_e : std::uint8_t { prompt, confirmed };

  [[nodiscard]] bool requires_termination_confirmation(bool terminate_on_first_request, bool caller_owns_active_game);

  [[nodiscard]] terminate_confirmation_e arm_or_confirm_termination(
    std::string_view client_uuid,
    std::uint64_t generation,
    std::int32_t app_id,
    std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now()
  );
  [[nodiscard]] std::string_view termination_confirmation_message();
  void clear_termination_confirmation(std::string_view client_uuid);

  [[nodiscard]] app_replacement_confirmation_e arm_or_confirm_app_replacement(
    std::string_view client_uuid,
    std::uint64_t generation,
    std::int32_t requested_app_id,
    std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now()
  );
  [[nodiscard]] bool app_replacement_confirmation_active(
    std::string_view client_uuid,
    std::uint64_t generation,
    std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now()
  );
  [[nodiscard]] std::string_view app_replacement_confirmation_message();
  void clear_app_replacement_confirmation(std::string_view client_uuid);

  struct pending_t {
    std::uint32_t launch_id {};
    std::string client_uuid;
    std::string crypto_binding;
    std::string source_address;
    bool encrypted {};
    role_e role {role_e::game};
    std::uint64_t generation {};
    std::chrono::steady_clock::time_point expires_at {};
  };

  struct monitor_runtime_state_t {
    bool accepted {};
    bool ready {};
    bool retryable {};
    std::string output;
    std::string error;
    bool hdr_enabled = false;
  };

  struct monitor_runtime_hooks_t {
    std::function<monitor_runtime_state_t(std::string_view client_uuid, std::string_view client_label, std::string_view requested_mode, bool hdr_requested, std::uint64_t generation)> activate_or_resume;
    std::function<monitor_runtime_state_t(std::string_view client_uuid, std::uint64_t generation)> snapshot;
    std::function<void(std::string_view client_uuid, std::uint64_t generation, std::string_view reason)> explicit_release;
    std::function<void(std::string_view client_uuid, std::uint64_t generation)> transport_lost;
    std::function<void(std::string_view client_uuid)> unpair;
    std::function<void()> shutdown;
  };

  enum class capture_source_e : std::uint8_t { active_output, exact_output, synthetic_black, invalid };

  struct capture_plan_t {
    capture_source_e source {capture_source_e::active_output};
    std::optional<std::string> output;
  };

  struct placement_t {
    std::string client_uuid;
    std::string anchor_kind;
    std::string anchor_id;
    std::string edge;
    std::string alignment;
    int gap_px {};
    bool primary {};
  };

  [[nodiscard]] bool reserved_name(std::string_view name);
  [[nodiscard]] control_e identify(std::int32_t id, std::string_view uuid = {});
  [[nodiscard]] control_e identify(std::int32_t id, std::string_view uuid, std::int32_t running_app_id);
  [[nodiscard]] std::string synthetic_uuid(control_e control);
  [[nodiscard]] app_t synthetic(control_e control);
  [[nodiscard]] std::int32_t synthetic_running_game_id(std::int32_t app_id);
  [[nodiscard]] app_t synthetic_running_game(const app_t &game);
  [[nodiscard]] std::optional<std::string_view> synthetic_artwork_filename(control_e control);
  [[nodiscard]] bool exposes_active_game(
    const caller_t &caller,
    const game_t &game,
    const owner_t &owner,
    bool remote_sessions_active,
    bool replacement_confirmation_active = false
  );
  [[nodiscard]] bool allows_normal_game_cancel(const caller_t &caller, const game_t &game, bool remote_sessions_active);
  [[nodiscard]] projection_t project(const caller_t &caller, const game_t &game, const owner_t &owner, const std::vector<app_t> &configured, bool remote_sessions_active);
  [[nodiscard]] dispatch_t dispatch(const caller_t &caller, const game_t &game, const owner_t &owner, control_e control);
  /** Join the running game's output while a peer owns it or a paused game retains a capture-ready output. */
  [[nodiscard]] bool joins_existing_game_output(
    role_e role,
    bool stream_active,
    bool retained_output_ready = false
  );
  [[nodiscard]] bool is_secondary_game_client(std::string_view app_owner_uuid, std::string_view caller_uuid);
  [[nodiscard]] std::string_view stream_start_response_key(bool launched_from_applist);
  [[nodiscard]] std::optional<control_completion_t> successful_control_completion(control_e control);
  [[nodiscard]] bool input_uses_display_or_audio(role_e role);
  [[nodiscard]] bool uses_audio(role_e role, bool mute_remote_monitor);
  // Remote Monitor keeps host playback enabled independently of the client's
  // localAudioPlayMode request. remote_monitor_mute_audio separately controls
  // whether the monitor receives an audio stream at all.
  [[nodiscard]] bool uses_host_audio(role_e role);
  [[nodiscard]] bool disconnect_monitor_after_stream(bool disconnect_on_stream_end, bool disconnect_on_client_disconnect, bool client_disconnected);
  [[nodiscard]] capture_plan_t capture_plan(role_e role, std::optional<std::string> output = std::nullopt);

  class normal_app_transition_gate_t {
  public:
    void lock() { mutex_.lock(); }
    bool try_lock() { return mutex_.try_lock(); }
    void unlock() { mutex_.unlock(); }

  private:
    std::mutex mutex_;
  };

  void register_monitor_runtime_hooks(monitor_runtime_hooks_t hooks);
  [[nodiscard]] monitor_runtime_state_t activate_or_resume_monitor(std::string_view client_uuid, std::string_view client_label, std::string_view requested_mode, bool hdr_requested, std::uint64_t generation);
  [[nodiscard]] monitor_runtime_state_t monitor_runtime_snapshot(std::string_view client_uuid, std::uint64_t generation);
  void release_monitor(std::string_view client_uuid, std::uint64_t generation, std::string_view reason);
  void notify_monitor_transport_lost(std::string_view client_uuid, std::uint64_t generation);
  void notify_monitor_unpair(std::string_view client_uuid);
  void notify_monitor_shutdown();

  class pending_registry_t {
  public:
    bool add(pending_t pending, std::string *warning = nullptr);
    std::optional<pending_t> match_encrypted(std::string_view client_uuid, std::string_view crypto_binding, std::chrono::steady_clock::time_point now);
    std::optional<pending_t> match_plaintext(std::string_view address, std::chrono::steady_clock::time_point now);
    void erase(std::uint32_t id);
    void expire(std::chrono::steady_clock::time_point now);
    void clear();
    [[nodiscard]] std::string warning() const;
  private:
    std::unordered_map<std::uint32_t, pending_t> pending_;
    std::string warning_;
  };

  [[nodiscard]] bool validate_layout(const std::vector<placement_t> &placements, const std::vector<std::string> &known_clients, const std::vector<std::string> &physical_ids, std::string *error);
}