Ctrl K
ComunidadGuías…

server/tools/display_settings_helper_v2.cpp

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

Archivo original ↗Preguntar a KiBot
/**
 * @file tools/display_settings_helper_v2.cpp
 * @brief Display helper v2 engine: modern FSM-based engine with the legacy
 *        helper's battle-tested restore semantics.
 */
#ifdef _WIN32

  #include <algorithm>
  #include <array>
  #include <atomic>
  #include <chrono>
  #include <cctype>
  #include <cstdint>
  #include <cstring>
  #include <deque>
  #include <filesystem>
  #include <fstream>
  #include <memory>
  #include <mutex>
  #include <optional>
  #include <set>
  #include <span>
  #include <string>
  #include <thread>
  #include <type_traits>
  #include <utility>
  #include <vector>
  #include <variant>

  #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
  #endif
  #include <winsock2.h>
  #include <windows.h>

  #include "src/logging.h"
  #include "src/platform/windows/display_helper_v2/async_dispatcher.h"
  #include "src/platform/windows/display_helper_v2/file_text_storage.h"
  #include "src/platform/windows/display_helper_v2/golden_health.h"
  #include "src/platform/windows/display_helper_v2/operations.h"
  #include "src/platform/windows/display_helper_v2/runtime_support.h"
  #include "src/platform/windows/display_helper_v2/snapshot.h"
  #include "src/platform/windows/display_helper_v2/snapshot_codec.h"
  #include "src/platform/windows/display_helper_v2/snapshot_file_storage.h"
  #include "src/platform/windows/display_helper_v2/state_machine.h"
  #include "src/platform/windows/display_helper_v2/win_display_settings.h"
  #include "src/platform/windows/display_helper_v2/win_event_pump.h"
  #include "src/platform/windows/display_helper_v2/win_platform_workarounds.h"
  #include "src/platform/windows/display_helper_v2/win_scheduled_task_manager.h"
  #include "src/platform/windows/display_helper_v2/win_virtual_display_driver.h"
  #include "src/platform/windows/ipc/pipes.h"
  #include "tools/display_helper_paths.h"

  #include <display_device/json.h>
  #include <display_device/logging.h>
  #include <nlohmann/json.hpp>

namespace {
  enum class MsgType : uint8_t {
    Apply = 1,
    Revert = 2,
    Reset = 3,
    ExportGolden = 4,
    LogLevel = 5,
    ApplyResult = 6,
    Disarm = 7,
    SnapshotCurrent = 8,
    VerificationResult = 9,
    RefreshRate = 10,
    RefreshRateResult = 11,
    SnapshotResult = 12,
    Ping = 0xFE,
    Stop = 0xFF,
  };

  std::optional<int> parse_log_level_value(const char *value) {
    if (!value || *value == '\0') {
      return std::nullopt;
    }

    std::string lower(value);
    std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char ch) {
      return static_cast<char>(std::tolower(ch));
    });

    if (lower == "verbose") {
      return 0;
    }
    if (lower == "debug") {
      return 1;
    }
    if (lower == "info") {
      return 2;
    }
    if (lower == "warning") {
      return 3;
    }
    if (lower == "error") {
      return 4;
    }
    if (lower == "fatal") {
      return 5;
    }
    if (lower == "none") {
      return 6;
    }
    if (lower.size() == 1 && lower[0] >= '0' && lower[0] <= '6') {
      return lower[0] - '0';
    }

    return std::nullopt;
  }

  std::optional<std::uint32_t> read_u32_le(std::span<const std::uint8_t> payload, std::size_t offset) {
    if (offset + 4 > payload.size()) {
      return std::nullopt;
    }
    return static_cast<std::uint32_t>(payload[offset]) |
           (static_cast<std::uint32_t>(payload[offset + 1]) << 8u) |
           (static_cast<std::uint32_t>(payload[offset + 2]) << 16u) |
           (static_cast<std::uint32_t>(payload[offset + 3]) << 24u);
  }

  std::optional<std::uint64_t> read_u64_le(std::span<const std::uint8_t> payload, std::size_t offset) {
    if (offset + 8 > payload.size()) {
      return std::nullopt;
    }
    std::uint64_t value = 0;
    for (unsigned int shift = 0; shift < 64; shift += 8) {
      value |= static_cast<std::uint64_t>(payload[offset + (shift / 8)]) << shift;
    }
    return value;
  }

  void append_u64_le(std::vector<std::uint8_t> &payload, std::uint64_t value) {
    for (unsigned int shift = 0; shift < 64; shift += 8) {
      payload.push_back(static_cast<std::uint8_t>((value >> shift) & 0xffu));
    }
  }

  constexpr std::uint32_t kV2RefreshRateMagic = 0x32524653u;  // "SFR2" in little-endian bytes.

  void send_framed_content(platf::dxgi::AsyncNamedPipe &pipe, MsgType type, std::span<const uint8_t> payload = {}) {
    std::vector<uint8_t> out;
    out.reserve(1 + payload.size());
    out.push_back(static_cast<uint8_t>(type));
    out.insert(out.end(), payload.begin(), payload.end());
    pipe.send(out);
  }

  /// Owns the currently connected control pipe without allowing a completion
  /// from an earlier connection to reply through a later one. The mutex stays
  /// held through send() so teardown cannot destroy the pipe while a response
  /// is being framed and written.
  class ActivePipeResponder {
  public:
    void bind(platf::dxgi::AsyncNamedPipe &pipe, std::uint64_t epoch) {
      std::lock_guard<std::mutex> lock(mutex_);
      pipe_ = &pipe;
      epoch_ = epoch;
    }

    void clear(std::uint64_t epoch) {
      std::lock_guard<std::mutex> lock(mutex_);
      if (epoch_ == epoch) {
        pipe_ = nullptr;
        epoch_ = 0;
      }
    }

    void send_for_epoch(std::uint64_t epoch, MsgType type, std::span<const uint8_t> payload = {}) {
      std::lock_guard<std::mutex> lock(mutex_);
      if (!pipe_ || epoch_ != epoch) {
        return;
      }
      send_framed_content(*pipe_, type, payload);
    }

  private:
    std::mutex mutex_;
    platf::dxgi::AsyncNamedPipe *pipe_ = nullptr;
    std::uint64_t epoch_ = 0;
  };

  bool is_replacement_control_intent(const display_helper::v2::Message &message) {
    return std::holds_alternative<display_helper::v2::ApplyCommand>(message) ||
           std::holds_alternative<display_helper::v2::RevertCommand>(message) ||
           std::holds_alternative<display_helper::v2::DisarmCommand>(message) ||
           std::holds_alternative<display_helper::v2::ResetCommand>(message);
  }

  bool is_delayed_disconnect_verification_completion(const display_helper::v2::Message &message) {
    const auto *completion = std::get_if<display_helper::v2::VerificationCompleted>(&message);
    return completion && completion->purpose == display_helper::v2::VerificationPurpose::TransientDisconnect;
  }

  bool is_async_completion(const display_helper::v2::Message &message) {
    return std::holds_alternative<display_helper::v2::ApplyCompleted>(message) ||
           std::holds_alternative<display_helper::v2::VerificationCompleted>(message) ||
           std::holds_alternative<display_helper::v2::ResetCompleted>(message) ||
           std::holds_alternative<display_helper::v2::RefreshRateCompleted>(message) ||
           std::holds_alternative<display_helper::v2::RecoveryCompleted>(message) ||
           std::holds_alternative<display_helper::v2::RecoveryValidationCompleted>(message);
  }

  bool is_ipc_ingress_from_epoch(const display_helper::v2::Message &message, std::uint64_t epoch) {
    return std::visit([epoch](const auto &payload) {
      using T = std::decay_t<decltype(payload)>;
      if constexpr (
        std::is_same_v<T, display_helper::v2::ApplyCommand> ||
        std::is_same_v<T, display_helper::v2::RevertCommand> ||
        std::is_same_v<T, display_helper::v2::DisarmCommand> ||
        std::is_same_v<T, display_helper::v2::ExportGoldenCommand> ||
        std::is_same_v<T, display_helper::v2::SnapshotCurrentCommand> ||
        std::is_same_v<T, display_helper::v2::RefreshRateCommand> ||
        std::is_same_v<T, display_helper::v2::ResetCommand> ||
        std::is_same_v<T, display_helper::v2::PingCommand> ||
        std::is_same_v<T, display_helper::v2::StopCommand> ||
        std::is_same_v<T, display_helper::v2::HelperEventMessage>) {
        return payload.connection_epoch == epoch;
      } else {
        return false;
      }
    }, message);
  }

  std::vector<std::string> parse_snapshot_exclude_json_node(const nlohmann::json &node) {
    std::vector<std::string> ids;
    const nlohmann::json *arr = &node;
    nlohmann::json nested;
    if (node.is_object()) {
      if (node.contains("exclude_devices")) {
        nested = node["exclude_devices"];
        arr = &nested;
      } else if (node.contains("devices")) {
        nested = node["devices"];
        arr = &nested;
      }
    }

    if (!arr->is_array()) {
      return ids;
    }

    for (const auto &el : *arr) {
      if (el.is_string()) {
        ids.push_back(el.get<std::string>());
      } else if (el.is_object()) {
        if (el.contains("device_id") && el["device_id"].is_string()) {
          ids.push_back(el["device_id"].get<std::string>());
        } else if (el.contains("id") && el["id"].is_string()) {
          ids.push_back(el["id"].get<std::string>());
        }
      }
    }

    return ids;
  }

  std::optional<std::vector<std::string>> parse_snapshot_exclude_payload(std::span<const uint8_t> payload) {
    if (payload.empty()) {
      return std::nullopt;
    }

    try {
      std::string raw(reinterpret_cast<const char *>(payload.data()), payload.size());
      if (raw.empty()) {
        return std::vector<std::string> {};
      }
      auto j = nlohmann::json::parse(raw, nullptr, false);
      if (j.is_discarded()) {
        return std::nullopt;
      }
      // A correlated v2 snapshot can carry only sunshine_snapshot_id. That is
      // completion metadata, not an instruction to replace the persistent
      // exclusion list with an empty one.
      if (j.is_object() && !j.contains("exclude_devices") && !j.contains("devices")) {
        return std::nullopt;
      }
      return parse_snapshot_exclude_json_node(j);
    } catch (...) {
      return std::nullopt;
    }
  }

  std::uint64_t parse_snapshot_request_id(std::span<const uint8_t> payload) {
    if (payload.empty()) {
      return 0;
    }
    try {
      std::string raw(reinterpret_cast<const char *>(payload.data()), payload.size());
      const auto json = nlohmann::json::parse(raw, nullptr, false);
      if (json.is_object() && json.contains("sunshine_snapshot_id") && json["sunshine_snapshot_id"].is_number_unsigned()) {
        return json["sunshine_snapshot_id"].get<std::uint64_t>();
      }
    } catch (...) {
    }
    return 0;
  }

  /**
   * @brief Load snapshot exclusions from vibeshine_state.json: the user-configured
   *        exclusion list merged with all Sunshine-managed virtual display ids so
   *        they are never captured into (or restored from) display baselines (f3841ad8).
   */
  bool load_vibeshine_snapshot_exclusions(const std::filesystem::path &path, std::vector<std::string> &ids_out) {
    ids_out.clear();
    if (path.empty()) {
      return false;
    }

    std::error_code ec;
    if (!std::filesystem::exists(path, ec) || ec) {
      return false;
    }

    try {
      std::ifstream file(path, std::ios::binary);
      if (!file) {
        return false;
      }
      auto j = nlohmann::json::parse(file, nullptr, false);
      if (!j.is_object() || !j.contains("root") || !j["root"].is_object()) {
        return false;
      }
      const auto &root = j["root"];
      bool found = false;
      if (root.contains("snapshot_exclude_devices")) {
        ids_out = parse_snapshot_exclude_json_node(root["snapshot_exclude_devices"]);
        found = !ids_out.empty() || root["snapshot_exclude_devices"].is_array();
      }
      if (root.contains("virtual_display_devices")) {
        auto virtual_ids = parse_snapshot_exclude_json_node(root["virtual_display_devices"]);
        for (auto &id : virtual_ids) {
          if (std::find(ids_out.begin(), ids_out.end(), id) == ids_out.end()) {
            ids_out.push_back(std::move(id));
          }
        }
        found = found || !ids_out.empty();
      }
      return found;
    } catch (...) {
      return false;
    }
  }

  bool parse_apply_payload(
    std::span<const uint8_t> payload,
    display_helper::v2::ApplyRequest &out_request,
    std::string &error) {
    std::string json(reinterpret_cast<const char *>(payload.data()), payload.size());
    std::string sanitized_json = json;

    try {
      auto j = nlohmann::json::parse(json, nullptr, false);
      if (j.is_object()) {
        if (j.contains("sunshine_apply_id") && j["sunshine_apply_id"].is_number_unsigned()) {
          out_request.request_id = j["sunshine_apply_id"].get<std::uint64_t>();
          j.erase("sunshine_apply_id");
        }
        if (j.contains("sunshine_omit_final_initial_hdr_reapply")) {
          out_request.omit_final_initial_hdr_reapply =
            j["sunshine_omit_final_initial_hdr_reapply"].is_boolean() &&
            j["sunshine_omit_final_initial_hdr_reapply"].get<bool>();
          j.erase("sunshine_omit_final_initial_hdr_reapply");
        }
        if (j.contains("wa_hdr_toggle")) {
          out_request.hdr_blank = j["wa_hdr_toggle"].get<bool>();
          j.erase("wa_hdr_toggle");
        }
        if (j.contains("sunshine_virtual_layout") && j["sunshine_virtual_layout"].is_string()) {
          out_request.virtual_layout = j["sunshine_virtual_layout"].get<std::string>();
          j.erase("sunshine_virtual_layout");
        }
        if (j.contains("sunshine_monitor_positions") && j["sunshine_monitor_positions"].is_object()) {
          for (auto it = j["sunshine_monitor_positions"].begin(); it != j["sunshine_monitor_positions"].end(); ++it) {
            const auto &node = it.value();
            if (!node.is_object()) {
              continue;
            }
            auto x_it = node.find("x");
            auto y_it = node.find("y");
            if (x_it == node.end() || y_it == node.end() || !x_it->is_number_integer() || !y_it->is_number_integer()) {
              continue;
            }
            out_request.monitor_positions.emplace_back(
              it.key(),
              display_device::Point {x_it->get<int>(), y_it->get<int>()}
            );
          }
          j.erase("sunshine_monitor_positions");
        }
        if (j.contains("sunshine_snapshot_exclude_devices")) {
          out_request.snapshot_exclusions = parse_snapshot_exclude_json_node(j["sunshine_snapshot_exclude_devices"]);
          j.erase("sunshine_snapshot_exclude_devices");
        }
        if (j.contains("sunshine_topology") && j["sunshine_topology"].is_array()) {
          display_device::ActiveTopology topo;
          for (const auto &grp_node : j["sunshine_topology"]) {
            if (!grp_node.is_array()) {
              continue;
            }
            std::vector<std::string> group;
            for (const auto &id_node : grp_node) {
              if (id_node.is_string()) {
                group.push_back(id_node.get<std::string>());
              }
            }
            if (!group.empty()) {
              topo.push_back(std::move(group));
            }
          }
          if (!topo.empty()) {
            out_request.topology = std::move(topo);
          }
          j.erase("sunshine_topology");
        }
        if (j.contains("sunshine_always_restore_from_golden") && j["sunshine_always_restore_from_golden"].is_boolean()) {
          out_request.prefer_golden_first = j["sunshine_always_restore_from_golden"].get<bool>();
          j.erase("sunshine_always_restore_from_golden");
        }
        if (j.contains("sunshine_restore_on_disconnect") && j["sunshine_restore_on_disconnect"].is_boolean()) {
          out_request.restore_on_disconnect = j["sunshine_restore_on_disconnect"].get<bool>();
          j.erase("sunshine_restore_on_disconnect");
        } else {
          out_request.restore_on_disconnect = true;
        }
        if (j.contains("sunshine_device_refresh_rate_overrides") && j["sunshine_device_refresh_rate_overrides"].is_object()) {
          for (auto it = j["sunshine_device_refresh_rate_overrides"].begin(); it != j["sunshine_device_refresh_rate_overrides"].end(); ++it) {
            const auto &node = it.value();
            if (!node.is_object()) {
              continue;
            }
            auto num_it = node.find("num");
            auto den_it = node.find("den");
            if (num_it == node.end() || den_it == node.end() || !num_it->is_number_unsigned() || !den_it->is_number_unsigned()) {
              continue;
            }
            out_request.refresh_rate_overrides.emplace_back(
              it.key(),
              std::make_pair(num_it->get<unsigned int>(), den_it->get<unsigned int>())
            );
          }
          j.erase("sunshine_device_refresh_rate_overrides");
        }
        sanitized_json = j.dump();
      }
    } catch (...) {
    }

    display_device::SingleDisplayConfiguration cfg {};
    std::string parse_error;
    if (!display_device::fromJson(sanitized_json, cfg, &parse_error)) {
      error = parse_error;
      return false;
    }

    out_request.configuration = std::move(cfg);
    return true;
  }

  void parse_revert_payload(std::span<const uint8_t> payload, display_helper::v2::RevertCommand &out) {
    if (payload.empty()) {
      return;
    }

    try {
      std::string raw(reinterpret_cast<const char *>(payload.data()), payload.size());
      auto j = nlohmann::json::parse(raw, nullptr, false);
      if (!j.is_object()) {
        return;
      }

      auto it = j.find("sunshine_prefer_golden_if_current_missing");
      if (it != j.end() && it->is_boolean()) {
        out.prefer_golden_if_current_missing = it->get<bool>();
      }

      it = j.find("sunshine_always_restore_from_golden");
      if (it != j.end() && it->is_boolean()) {
        out.always_restore_from_golden = it->get<bool>();
      }
    } catch (...) {
    }
  }

  bool parse_frame(
    std::span<const uint8_t> frame,
    MsgType &type,
    std::span<const uint8_t> &payload) {
    if (frame.empty()) {
      return false;
    }

    if (frame.size() >= 5) {
      uint32_t len = 0;
      std::memcpy(&len, frame.data(), sizeof(len));
      if (len > 0 && frame.size() >= 4u + len) {
        type = static_cast<MsgType>(frame[4]);
        if (len > 1) {
          payload = std::span<const uint8_t>(frame.data() + 5, len - 1);
        } else {
          payload = {};
        }
        return true;
      }
    }

    type = static_cast<MsgType>(frame[0]);
    payload = frame.subspan(1);
    return true;
  }

  class DisplayDeviceLogBridge {
  public:
    void install() {
      display_device::Logger::get().setCustomCallback(
        [](display_device::Logger::LogLevel level, std::string message) {
          const auto prefixed = std::string("display_device: ") + message;
          switch (level) {
            case display_device::Logger::LogLevel::verbose:
            case display_device::Logger::LogLevel::debug:
              BOOST_LOG(debug) << prefixed;
              break;
            case display_device::Logger::LogLevel::info:
              BOOST_LOG(info) << prefixed;
              break;
            case display_device::Logger::LogLevel::warning:
              BOOST_LOG(warning) << prefixed;
              break;
            case display_device::Logger::LogLevel::error:
              BOOST_LOG(error) << prefixed;
              break;
            case display_device::Logger::LogLevel::fatal:
              BOOST_LOG(fatal) << prefixed;
              break;
          }
        }
      );
    }
  };

  /// Validate a snapshot file found in a search root; remove it when it has no
  /// usable restore payload (legacy validate_session_snapshot).
  bool validate_snapshot_file(const std::filesystem::path &path, const char *label) {
    display_helper::v2::AtomicFileTextStorage files;
    const auto text = files.read(path.string());
    if (!text) {
      return false;
    }
    if (display_helper::v2::codec::snapshot_text_has_restore_payload(*text)) {
      return true;
    }

    BOOST_LOG(warning) << "Existing " << label << " snapshot is missing restore topology/mode data; removing path=" << path.string();
    std::error_code ec_rm;
    std::filesystem::remove(path, ec_rm);
    return false;
  }

  /// Copy validated snapshots from any search root into the active snapshot dir
  /// so SYSTEM/user contexts and old install layouts share one restore chain.
  void adopt_snapshots_from_search_roots(
    const std::vector<std::filesystem::path> &search_roots,
    const std::filesystem::path &active_current,
    const std::filesystem::path &active_previous) {
    for (const auto &root : search_roots) {
      const auto paths = display_helper_paths::make_snapshot_paths(root);
      std::error_code ec_cur;
      if (std::filesystem::exists(paths.session_current, ec_cur) && !ec_cur) {
        if (validate_snapshot_file(paths.session_current, "session")) {
          BOOST_LOG(info) << "Existing current session snapshot detected; will preserve until confirmed restore: "
                          << paths.session_current.string();
          if (paths.session_current != active_current) {
            std::error_code ec_copy;
            std::filesystem::create_directories(active_current.parent_path(), ec_copy);
            std::filesystem::copy_file(paths.session_current, active_current, std::filesystem::copy_options::overwrite_existing, ec_copy);
          }
          break;
        }
      }
    }
    for (const auto &root : search_roots) {
      const auto paths = display_helper_paths::make_snapshot_paths(root);
      std::error_code ec_prev;
      if (std::filesystem::exists(paths.session_previous, ec_prev) && !ec_prev) {
        if (validate_snapshot_file(paths.session_previous, "session")) {
          if (paths.session_previous != active_previous) {
            std::error_code ec_copy;
            std::filesystem::create_directories(active_previous.parent_path(), ec_copy);
            std::filesystem::copy_file(paths.session_previous, active_previous, std::filesystem::copy_options::overwrite_existing, ec_copy);
          }
          break;
        }
      }
    }
  }
}  // namespace

int run_v2_helper(int argc, char *argv[]) {
  bool restore_mode = false;
  std::optional<int> log_level_override;
  constexpr const char *kLogLevelPrefix = "--log-level=";
  for (int i = 1; i < argc; ++i) {
    if (std::strcmp(argv[i], "--restore") == 0) {
      restore_mode = true;
    } else if (std::strcmp(argv[i], "--log-level") == 0 && (i + 1) < argc) {
      if (auto parsed = parse_log_level_value(argv[i + 1])) {
        log_level_override = *parsed;
      }
      ++i;
    } else if (std::strncmp(argv[i], kLogLevelPrefix, std::strlen(kLogLevelPrefix)) == 0) {
      if (auto parsed = parse_log_level_value(argv[i] + std::strlen(kLogLevelPrefix))) {
        log_level_override = *parsed;
      }
    }
  }

  if (restore_mode) {
    FreeConsole();
    display_helper_paths::hide_console_window();
  }

  // Initialize logging early so we can log singleton conflicts and other early exits
  const auto log_dir = display_helper_paths::compute_log_dir();
  const auto snapshot_dir = display_helper_paths::compute_snapshot_dir();
  const auto log_file = log_dir / L"sunshine_display_helper.log";
  const int min_log_level = log_level_override.value_or(2);
  auto log_guard = logging::init(min_log_level, log_file);

  BOOST_LOG(info) << "Display helper v2 starting up" << (restore_mode ? " (restore mode)" : "") << "...";

  HANDLE singleton = nullptr;
  if (!display_helper_paths::ensure_single_instance(singleton)) {
    BOOST_LOG(warning) << "Display helper: another instance is already running (singleton conflict). Exiting with code 3.";
    logging::log_flush();
    return 3;
  }

  DisplayDeviceLogBridge log_bridge;
  log_bridge.install();

  const auto active_snapshots = display_helper_paths::make_snapshot_paths(snapshot_dir);
  const auto search_roots = display_helper_paths::snapshot_search_roots();

  display_helper::v2::SystemClock clock;
  // Keep this alive longer than AsyncDispatcher: a refresh completion can
  // otherwise outlive the currently connected pipe during helper shutdown.
  ActivePipeResponder response_pipe;
  display_helper::v2::WinDisplaySettings display_settings;
  display_helper::v2::SnapshotService snapshot_service(display_settings);

  display_helper::v2::SnapshotPaths paths {
    .current = active_snapshots.session_current,
    .previous = active_snapshots.session_previous,
    .golden = active_snapshots.golden,
  };
  display_helper::v2::FileSnapshotStorage storage(paths);
  display_helper::v2::SnapshotPersistence persistence(storage);
  display_helper::v2::AtomicFileTextStorage golden_status_storage;
  display_helper::v2::GoldenHealth golden_health(golden_status_storage, active_snapshots.golden_status.string());
  display_helper::v2::RestoreState restore_state;
  display_helper::v2::ApplyPolicy apply_policy(clock);
  display_helper::v2::WinVirtualDisplayDriver virtual_display;
  display_helper::v2::WinPlatformWorkarounds workarounds;
  display_helper::v2::WinScheduledTaskManager task_manager;
  display_helper::v2::HeartbeatMonitor heartbeat(clock);
  display_helper::v2::CancellationSource cancellation;
  display_helper::v2::SystemPorts system_ports(workarounds, task_manager, heartbeat, clock, cancellation);
  display_helper::v2::ApplyOperation apply_operation(
    display_settings,
    clock,
    [&task_manager]() {
      return task_manager.create_restore_task(L"");
    });
  display_helper::v2::VerificationOperation verification_operation(display_settings, clock);
  display_helper::v2::RecoveryOperation recovery_operation(display_settings, storage, golden_health, restore_state, clock);
  display_helper::v2::RecoveryValidationOperation recovery_validation(snapshot_service, clock);

  // Completion callbacks owned by AsyncDispatcher enqueue onto this queue.
  // Keep the queue alive until after the dispatcher has joined its workers at
  // shutdown; declaring it first gives the local objects that destruction
  // order without a second shutdown protocol.
  display_helper::v2::MessageQueue<display_helper::v2::Message> queue;
  display_helper::v2::AsyncDispatcher dispatcher(
    apply_operation,
    verification_operation,
    recovery_operation,
    recovery_validation,
    virtual_display,
    clock
  );

  std::atomic<bool> running {true};

  // Adopt snapshots written by other contexts (SYSTEM vs user) or the legacy engine.
  adopt_snapshots_from_search_roots(search_roots, paths.current, paths.previous);

  // A payload-less golden file (e.g. a crash-truncated overwrite) makes the
  // restore strategy see an existing-but-unloadable golden tier; drop it so
  // tier existence stays consistent with loadability.
  {
    std::error_code ec_golden;
    if (std::filesystem::exists(paths.golden, ec_golden) && !ec_golden) {
      (void) validate_snapshot_file(paths.golden, "golden");
    }
  }

  // Load snapshot exclusions (user-configured + Sunshine-managed virtual display ids).
  std::set<std::string> initial_blacklist;
  for (const auto &root : search_roots) {
    std::vector<std::string> exclusions;
    const auto state_file = root / L"vibeshine_state.json";
    if (load_vibeshine_snapshot_exclusions(state_file, exclusions)) {
      BOOST_LOG(info) << "Loaded snapshot exclusions from vibeshine_state.json (" << exclusions.size()
                      << ") at " << state_file.string();
      for (auto &id : exclusions) {
        if (!id.empty()) {
          initial_blacklist.insert(std::move(id));
        }
      }
      break;
    }
  }

  auto enqueue_message = [&](display_helper::v2::Message message) {
    queue.push(std::move(message));
  };
  display_helper::v2::ApplyPipeline apply_pipeline(dispatcher, apply_policy, system_ports, enqueue_message);
  display_helper::v2::RecoveryPipeline recovery_pipeline(dispatcher, system_ports, enqueue_message);
  display_helper::v2::SnapshotLedger snapshot_ledger(snapshot_service, persistence, clock);

  display_helper::v2::StateMachine state_machine(
    apply_pipeline,
    recovery_pipeline,
    snapshot_ledger,
    system_ports,
    virtual_display,
    golden_health,
    restore_state);

  state_machine.set_snapshot_blacklist(std::move(initial_blacklist));

  // Connection epochs: ignore stale pipe callbacks and decide whether a confirmed
  // restore should exit the helper or keep it alive for a newer connection.
  std::atomic<uint64_t> connection_epoch {0};
  // Pipe ownership consumes this one-shot request and performs the same epoch
  // retirement path used for a physical disconnect. Keeping it separate from
  // the FSM event queue prevents a hung-but-connected client from holding the
  // listener through restore/retry work.
  std::atomic<uint64_t> heartbeat_disconnect_epoch {0};
  std::atomic<uint64_t> restore_origin_epoch {0};
  std::atomic<bool> client_connected {false};
  state_machine.set_connection_epoch_provider([&connection_epoch] {
    return connection_epoch.load(std::memory_order_acquire);
  });

  int exit_code = 0;
  state_machine.set_exit_callback([&](int code) {
    const auto origin = restore_origin_epoch.load(std::memory_order_acquire);
    const auto current = connection_epoch.load(std::memory_order_acquire);
    if (code == 0 && origin != 0 && current > origin && client_connected.load(std::memory_order_acquire)) {
      BOOST_LOG(info) << "Restore confirmed while newer connection active; helper remains running.";
      restore_origin_epoch.store(0, std::memory_order_release);
      return;
    }
    exit_code = code;
    // Dispatcher workers use this generation token at every mutation
    // boundary. Retire it before local teardown so no recovery/apply stage
    // continues after the helper has decided to exit.
    cancellation.cancel();
    running.store(false, std::memory_order_release);
  });

  state_machine.set_apply_result_callback([&response_pipe](display_helper::v2::ApplyStatus status, std::uint64_t origin_epoch, std::uint64_t request_id) {
    std::vector<uint8_t> payload;
    payload.push_back(status == display_helper::v2::ApplyStatus::Ok ? 1u : 0u);
    append_u64_le(payload, request_id);
    response_pipe.send_for_epoch(origin_epoch, MsgType::ApplyResult, payload);
  });
  state_machine.set_verification_result_callback([&response_pipe](bool success, std::uint64_t origin_epoch, std::uint64_t request_id) {
    std::vector<uint8_t> payload;
    payload.push_back(success ? 1u : 0u);
    append_u64_le(payload, request_id);
    response_pipe.send_for_epoch(origin_epoch, MsgType::VerificationResult, payload);
  });
  state_machine.set_snapshot_result_callback([&response_pipe](bool success, std::uint64_t origin_epoch, std::uint64_t request_id) {
    if (request_id == 0) {
      // SNAPSHOT_CURRENT has historically been dispatch-only. Only the
      // explicitly correlated v2 command produces a reply, avoiding a stale
      // fire-and-forget result in a later session's response lane.
      return;
    }
    std::vector<std::uint8_t> payload;
    payload.push_back(success ? 1u : 0u);
    append_u64_le(payload, request_id);
    response_pipe.send_for_epoch(origin_epoch, MsgType::SnapshotResult, payload);
  });
  state_machine.set_refresh_rate_result_callback([&response_pipe](bool success, std::uint64_t origin_epoch, std::uint64_t request_id) {
    std::vector<std::uint8_t> payload;
    payload.push_back(success ? 1u : 0u);
    if (request_id != 0) {
      append_u64_le(payload, request_id);
    }
    response_pipe.send_for_epoch(origin_epoch, MsgType::RefreshRateResult, payload);
  });

  display_helper::v2::DebouncedTrigger debouncer(std::chrono::milliseconds(500));
  std::mutex debounce_mutex;
  display_helper::v2::WinEventPump event_pump;
  event_pump.start([&](display_helper::v2::DisplayEvent event) {
    std::lock_guard<std::mutex> lock(debounce_mutex);
    // Tag at notification time. A WM_DISPLAYCHANGE emitted by a cancelled
    // transaction must not be relabelled as an event for a newer APPLY when
    // the debounce delay expires.
    debouncer.notify(
      clock.now(),
      cancellation.current_generation(),
      connection_epoch.load(std::memory_order_acquire),
      event);
  });

  auto service_timers = [&]() {
    if (heartbeat.check_timeout()) {
      const auto origin_epoch = connection_epoch.load(std::memory_order_acquire);
      if (origin_epoch != 0) {
        BOOST_LOG(warning) << "Heartbeat timed out; retiring the live IPC connection before recovery.";
        heartbeat_disconnect_epoch.store(origin_epoch, std::memory_order_release);
      }
    }

    std::optional<display_helper::v2::DebouncedTrigger::Ticket> display_event;
    {
      std::lock_guard<std::mutex> lock(debounce_mutex);
      display_event = debouncer.take_if_due(clock.now());
    }
    if (display_event) {
      queue.push(display_helper::v2::DisplayEventMessage {
        .event = display_event->event,
        .generation = display_event->generation,
        .connection_epoch = display_event->connection_epoch,
      });
    }

    state_machine.handle_tick();
  };

  auto process_queue = [&]() {
    if (auto message = queue.wait_for(std::chrono::milliseconds(100))) {
      // A delayed disconnect-verification completion may race a replacement
      // APPLY/REVERT/DISARM or refresh command arriving from the pipe. Give a
      // contiguous replacement-intent prefix priority so the state machine can
      // coalesce it behind the active mutation fence before that completion
      // decides what to run next. This is v2 mailbox ownership, not v1's
      // background-worker mutex choreography.
      std::deque<display_helper::v2::Message> controls;
      // Do not cross a normal IPC ingress frame such as SNAPSHOT_CURRENT: its
      // pipe order is a baseline-capture contract. Only a contiguous control
      // prefix immediately following an asynchronous completion may supersede
      // that completion.
      const bool prioritize_refresh_rate = is_delayed_disconnect_verification_completion(*message);
      auto queued_controls = is_async_completion(*message) ?
                               queue.extract_prefix_while([prioritize_refresh_rate](const display_helper::v2::Message &queued) {
                                 return is_replacement_control_intent(queued) ||
                                        (prioritize_refresh_rate &&
                                         (std::holds_alternative<display_helper::v2::RefreshRateCommand>(queued) ||
                                          std::holds_alternative<display_helper::v2::PingCommand>(queued)));
                               }) :
                               std::deque<display_helper::v2::Message> {};
      while (!queued_controls.empty()) {
        controls.emplace_back(std::move(queued_controls.front()));
        queued_controls.pop_front();
      }
      while (!controls.empty()) {
        state_machine.handle_message(controls.front());
        controls.pop_front();
      }
      state_machine.handle_message(*message);
    }
    // Timers must advance even while IPC/completion traffic is continuous.
    // Otherwise a busy helper can indefinitely postpone both heartbeat
    // recovery and restore-scheduler backoff.
    service_timers();
  };

  if (restore_mode) {
    BOOST_LOG(info) << "Display helper v2 running in restore mode.";
    display_helper::v2::RevertCommand revert {cancellation.current_generation()};
    revert.immediate = true;
    queue.push(revert);
    while (running.load(std::memory_order_acquire)) {
      process_queue();
    }
    event_pump.stop();
    BOOST_LOG(info) << "Display helper v2 restore mode completed with exit code " << exit_code << ".";
    logging::log_flush();
    return exit_code;
  }

  auto last_connect_wait_log = std::chrono::steady_clock::time_point::min();
  constexpr auto kReconnectLogInterval = std::chrono::hours(1);
  while (running.load(std::memory_order_acquire)) {
    platf::dxgi::FramedPipeFactory pipe_factory(std::make_unique<platf::dxgi::AnonymousPipeFactory>());
    auto server_pipe = pipe_factory.create_server("sunshine_display_helper");
    if (!server_pipe) {
      platf::dxgi::FramedPipeFactory fallback_factory(std::make_unique<platf::dxgi::NamedPipeFactory>());
      server_pipe = fallback_factory.create_server("sunshine_display_helper");
      if (!server_pipe) {
        BOOST_LOG(error) << "Failed to create control pipe; retrying while keeping recovery timers alive.";
        // Listener creation is incidental to recovery. Continue driving the
        // FSM and restore scheduler while it is unavailable, matching v1's
        // listener-independent restore poll.
        for (int retry_slice = 0; retry_slice < 5 && running.load(std::memory_order_acquire); ++retry_slice) {
          process_queue();
        }
        continue;
      }
    }

    platf::dxgi::AsyncNamedPipe async_pipe(std::move(server_pipe));

    // Wait for a client connection before starting the async worker. Without
    // this the cleanup path below would tear down the server pipe before
    // Sunshine ever had a chance to connect (28b048ac). Keep processing FSM
    // work (pending restores, ticks) while waiting.
    {
      const auto wait_deadline = std::chrono::steady_clock::now() + std::chrono::seconds(15);
      while (running.load(std::memory_order_acquire) && !async_pipe.is_connected() &&
             std::chrono::steady_clock::now() < wait_deadline) {
        async_pipe.wait_for_client_connection(100);
        process_queue();
      }
    }
    if (!running.load(std::memory_order_acquire)) {
      async_pipe.stop();
      break;
    }
    if (!async_pipe.is_connected()) {
      const auto now = std::chrono::steady_clock::now();
      if (now - last_connect_wait_log > kReconnectLogInterval) {
        BOOST_LOG(info) << "Waiting for Sunshine to connect to display helper IPC...";
        last_connect_wait_log = now;
      }
      async_pipe.stop();
      continue;
    }

    const auto epoch = connection_epoch.fetch_add(1, std::memory_order_acq_rel) + 1;
    heartbeat_disconnect_epoch.store(0, std::memory_order_release);
    client_connected.store(true, std::memory_order_release);
    // Match v1's per-connection watchdog lifecycle. This only resets
    // liveness timing; recovery remains owned by the state machine's lease.
    heartbeat.arm();
    response_pipe.bind(async_pipe, epoch);

    auto on_message = [&, epoch](std::span<const uint8_t> bytes) {
      if (connection_epoch.load(std::memory_order_acquire) != epoch) {
        return;
      }
      MsgType type {};
      std::span<const uint8_t> payload;
      if (!parse_frame(bytes, type, payload)) {
        return;
      }

      switch (type) {
        case MsgType::Apply: {
          display_helper::v2::ApplyRequest request;
          std::string parse_failure;
          if (!parse_apply_payload(payload, request, parse_failure)) {
            BOOST_LOG(error) << "Failed to parse SingleDisplayConfiguration JSON: " << parse_failure;
            std::vector<uint8_t> result_payload;
            result_payload.push_back(0u);
            append_u64_le(result_payload, request.request_id);
            if (!parse_failure.empty()) {
              result_payload.insert(result_payload.end(), parse_failure.begin(), parse_failure.end());
            }
            response_pipe.send_for_epoch(epoch, MsgType::ApplyResult, result_payload);
            return;
          }

          queue.push(display_helper::v2::ApplyCommand {std::move(request), cancellation.current_generation(), epoch});
          break;
        }
        case MsgType::Revert: {
          display_helper::v2::RevertCommand revert {cancellation.current_generation()};
          parse_revert_payload(payload, revert);
          revert.connection_epoch = epoch;
          restore_origin_epoch.store(epoch, std::memory_order_release);
          queue.push(revert);
          break;
        }
        case MsgType::Disarm:
          queue.push(display_helper::v2::DisarmCommand {
            .generation = cancellation.current_generation(),
            .connection_epoch = epoch,
            .force = !payload.empty() && payload.front() != 0,
          });
          break;
        case MsgType::ExportGolden: {
          display_helper::v2::SnapshotCommandPayload payload_struct;
          if (auto parsed = parse_snapshot_exclude_payload(payload)) {
            payload_struct.exclude_devices = std::move(*parsed);
            payload_struct.update_exclusions = true;
          }
          queue.push(display_helper::v2::ExportGoldenCommand {
            .payload = std::move(payload_struct),
            .generation = cancellation.current_generation(),
            .connection_epoch = epoch,
          });
          break;
        }
        case MsgType::SnapshotCurrent: {
          display_helper::v2::SnapshotCommandPayload payload_struct;
          if (auto parsed = parse_snapshot_exclude_payload(payload)) {
            payload_struct.exclude_devices = std::move(*parsed);
            payload_struct.update_exclusions = true;
          }
          queue.push(display_helper::v2::SnapshotCurrentCommand {
            .payload = std::move(payload_struct),
            .generation = cancellation.current_generation(),
            .connection_epoch = epoch,
            .request_id = parse_snapshot_request_id(payload),
          });
          break;
        }
        case MsgType::RefreshRate: {
          const auto first_word = read_u32_le(payload, 0);
          const bool correlated_v2 = first_word && *first_word == kV2RefreshRateMagic;
          const std::size_t rate_offset = correlated_v2 ? 4 : 0;
          const auto numerator = read_u32_le(payload, rate_offset);
          const auto denominator = read_u32_le(payload, rate_offset + 4);
          const std::uint64_t request_id = correlated_v2 ? read_u64_le(payload, rate_offset + 8).value_or(0) : 0;
          const std::size_t device_offset = correlated_v2 ? rate_offset + 16 : 8;
          std::string device_id;
          if (payload.size() > device_offset) {
            device_id.assign(
              reinterpret_cast<const char *>(payload.data() + device_offset),
              payload.size() - device_offset
            );
          }
          if (!numerator || !denominator || *numerator == 0 || *denominator == 0 || device_id.empty()) {
            std::vector<std::uint8_t> result {0u};
            if (request_id != 0) {
              append_u64_le(result, request_id);
            }
            response_pipe.send_for_epoch(epoch, MsgType::RefreshRateResult, result);
            break;
          }

          queue.push(display_helper::v2::RefreshRateCommand {
            .device_id = std::move(device_id),
            .numerator = *numerator,
            .denominator = *denominator,
            .generation = cancellation.current_generation(),
            .connection_epoch = epoch,
            .request_id = request_id,
          });
          break;
        }
        case MsgType::Reset:
          queue.push(display_helper::v2::ResetCommand {
            .generation = cancellation.current_generation(),
            .connection_epoch = epoch,
          });
          break;
        case MsgType::Ping:
          // Heartbeat liveness is time-sensitive rather than an ordered display
          // mutation. Record it at the pipe boundary (as v1 did) so a busy
          // FSM queue cannot turn an already received ping into a false
          // recovery. HeartbeatMonitor serializes this with the timer loop.
          heartbeat.record_ping();
          response_pipe.send_for_epoch(epoch, MsgType::Ping);
          break;
        case MsgType::LogLevel:
          if (!payload.empty()) {
            const int level = std::clamp(static_cast<int>(payload.front()), 0, 6);
            logging::reconfigure_min_log_level(level);
            BOOST_LOG(info) << "Display helper log level updated to " << level;
          }
          break;
        case MsgType::Stop:
          BOOST_LOG(info) << "Display helper: received STOP command, exiting gracefully.";
          cancellation.cancel();
          running.store(false, std::memory_order_release);
          break;
        default:
          BOOST_LOG(warning) << "Unknown message type: " << static_cast<int>(type);
          break;
      }
    };

    std::atomic<bool> broken {false};

    // Retire the epoch as soon as the pipe reports failure, rather than when
    // the main loop eventually reaches its cleanup. This makes every queued
    // command from the dead client stale before it can DISARM recovery or
    // overwrite the restore baseline, while async mutation completions retain
    // their generation-based ownership fences.
    auto retire_connection_epoch = [&, epoch](const char *reason) {
      std::uint64_t expected = epoch;
      if (!connection_epoch.compare_exchange_strong(
            expected,
            epoch + 1,
            std::memory_order_acq_rel,
            std::memory_order_acquire)) {
        BOOST_LOG(info) << "Ignoring " << reason << " from stale connection (epoch=" << epoch << ")";
        return false;
      }
      broken.store(true, std::memory_order_release);
      return true;
    };

    auto on_error = [&, epoch](const std::string &err) {
      if (!retire_connection_epoch("async pipe error")) {
        return;
      }
      BOOST_LOG(error) << "Async pipe error: " << err << "; handling disconnect and revert policy.";
    };

    auto on_broken = [&, epoch]() {
      if (!retire_connection_epoch("disconnect notification")) {
        return;
      }
      BOOST_LOG(warning) << "Client disconnected; applying revert policy.";
    };

    async_pipe.start(on_message, on_error, on_broken);

    while (running.load(std::memory_order_acquire)) {
      process_queue();

      if (heartbeat_disconnect_epoch.load(std::memory_order_acquire) == epoch) {
        (void) retire_connection_epoch("heartbeat timeout");
      }

      const bool connected = async_pipe.is_connected() && !broken.load(std::memory_order_acquire);
      client_connected.store(connected, std::memory_order_release);
      if (!connected) {
        // Some pipe implementations report a disconnected state before their
        // callback runs. Retire it here too; compare_exchange makes the
        // callback/main-loop paths one idempotent ownership transition.
        (void) retire_connection_epoch("disconnected pipe");
        response_pipe.clear(epoch);
        heartbeat.disarm();
        const auto discarded = queue.extract_if([epoch](const display_helper::v2::Message &queued) {
          return is_ipc_ingress_from_epoch(queued, epoch);
        });
        if (!discarded.empty()) {
          BOOST_LOG(debug) << "Discarded " << discarded.size()
                           << " queued command(s) from retired IPC epoch=" << epoch << ".";
        }
        // Sunshine disconnected or crashed. Arm the autonomous restore now (the
        // FSM applies a 5s grace and the restore-on-disconnect policy; a fast
        // reconnect supersedes it via DISARM/APPLY like the legacy engine), but
        // only when this helper actually changed something or a restore is
        // already being worked on.
        if (state_machine.begin_transient_disconnect_settlement()) {
          BOOST_LOG(info) << "Client disconnected shortly after APPLY; retaining the session for bounded settling verification instead of restoring.";
        } else if (state_machine.requires_disconnect_recovery()) {
          BOOST_LOG(info) << "Client disconnected; applying revert policy and staying alive until successful.";
          display_helper::v2::RevertCommand revert {cancellation.current_generation()};
          // This is a helper-owned recovery signal, not a command belonging to
          // the retired pipe. Zero is deliberately exempt from epoch filtering.
          revert.connection_epoch = 0;
          revert.from_disconnect = true;
          restore_origin_epoch.store(epoch, std::memory_order_release);
          state_machine.handle_message(revert);
        }
        break;
      }
    }

    response_pipe.clear(epoch);
    client_connected.store(false, std::memory_order_release);
    heartbeat.disarm();
    async_pipe.stop();
  }

  cancellation.cancel();
  event_pump.stop();
  BOOST_LOG(info) << "Display helper v2 shutting down with exit code " << exit_code << ".";
  logging::log_flush();
  return exit_code;
}

#endif  // _WIN32