From 94fdba405d72f71b90e8856b18ede1853c6aceac Mon Sep 17 00:00:00 2001 From: loki Date: Wed, 25 Dec 2019 23:41:46 +0100 Subject: [PATCH] resume and quit apps from Moonlight --- sunshine/nvhttp.cpp | 82 ++++++++++++++++++++++++++++++++++++++------ sunshine/process.cpp | 13 ++++--- sunshine/process.h | 4 +-- 3 files changed, 80 insertions(+), 19 deletions(-) diff --git a/sunshine/nvhttp.cpp b/sunshine/nvhttp.cpp index f2c45d31..25ec6a95 100644 --- a/sunshine/nvhttp.cpp +++ b/sunshine/nvhttp.cpp @@ -79,6 +79,8 @@ enum class op_e { REMOVE }; +std::int64_t current_appid { -1 }; + void save_devices() { pt::ptree root; @@ -409,7 +411,7 @@ void serverinfo(std::shared_ptr::Response> res } tree.put("root.PairStatus", pair_status); - tree.put("root.currentgame", 0); + tree.put("root.currentgame", current_appid >= 0 ? current_appid + 2 : 0); tree.put("root.state", "_SERVER_BUSY"); std::ostringstream data; @@ -468,12 +470,8 @@ template void launch(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { print_req(request); - static std::int64_t current_appid { -1 }; - pt::ptree tree; auto g = util::fail_guard([&]() { - tree.put("root.gamesession", 0); - std::ostringstream data; pt::write_xml(data, tree); @@ -487,6 +485,7 @@ void launch(std::shared_ptr::Response> respons if(stream::has_session) { tree.put("root..status_code", 503); + tree.put("root.gamesession", 0); return; } @@ -499,6 +498,7 @@ void launch(std::shared_ptr::Response> respons auto &apps = proc::proc.get_apps(); if(appid >= apps.size()) { tree.put("root..status_code", 404); + tree.put("root.gamesession", 0); return; } @@ -509,6 +509,7 @@ void launch(std::shared_ptr::Response> respons auto err = proc::proc.execute(pos->first); if(err) { tree.put("root..status_code", 500); + tree.put("root.gamesession", 0); return; } @@ -527,7 +528,7 @@ void launch(std::shared_ptr::Response> respons auto next = std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv)); std::fill(next, std::end(launch_session.iv), 0); - stream::launch_event.raise(std::move(launch_session)); + stream::launch_event.raise(launch_session); /* bool sops = args.at("sops"s) == "1"; @@ -537,14 +538,71 @@ void launch(std::shared_ptr::Response> respons } */ - g.disable(); tree.put("root..status_code", 200); tree.put("root.gamesession", 1); +} - std::ostringstream data; +template +void resume(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { + print_req(request); - pt::write_xml(data, tree); - response->write(data.str()); + pt::ptree tree; + auto g = util::fail_guard([&]() { + std::ostringstream data; + + pt::write_xml(data, tree); + response->write(data.str()); + }); + + stream::launch_session_t launch_session; + + if(stream::has_session) { + tree.put("root.gamesession", 0); + tree.put("root..status_code", 503); + + return; + } + + // Needed to determine if session must be closed when no process is running in proc::proc + launch_session.has_process = current_appid >= 0; + + auto args = request->parse_query_string(); + auto clientID = args.at("uniqueid"s); + launch_session.gcm_key = *util::from_hex(args.at("rikey"s), true); + uint32_t prepend_iv = util::endian::big(util::from_view(args.at("rikeyid"s))); + auto prepend_iv_p = (uint8_t*)&prepend_iv; + + auto next = std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv)); + std::fill(next, std::end(launch_session.iv), 0); + + stream::launch_event.raise(launch_session); + + tree.put("root..status_code", 200); + tree.put("root.gamesession", 1); +} + +template +void cancel(std::shared_ptr::Response> response, std::shared_ptr::Request> request) { + print_req(request); + + pt::ptree tree; + auto g = util::fail_guard([&]() { + std::ostringstream data; + + pt::write_xml(data, tree); + response->write(data.str()); + }); + + if(stream::has_session) { + tree.put("root..status_code", 503); + + return; + } + + proc::proc.terminate(); + current_appid = -1; + + tree.put("root..status_code", 200); } template @@ -576,6 +634,8 @@ void start() { https_server.resource["^/appasset$"]["GET"] = appasset; https_server.resource["^/launch$"]["GET"] = launch; https_server.resource["^/pin/([0-9]+)$"]["GET"] = pin; + https_server.resource["^/resume$"]["GET"] = resume; + https_server.resource["^/cancel$"]["GET"] = cancel; https_server.config.reuse_address = true; https_server.config.address = "0.0.0.0"s; @@ -588,6 +648,8 @@ void start() { http_server.resource["^/appasset$"]["GET"] = appasset; http_server.resource["^/launch$"]["GET"] = launch; http_server.resource["^/pin/([0-9]+)$"]["GET"] = pin; + http_server.resource["^/resume$"]["GET"] = resume; + http_server.resource["^/cancel$"]["GET"] = cancel; http_server.config.reuse_address = true; http_server.config.address = "0.0.0.0"s; diff --git a/sunshine/process.cpp b/sunshine/process.cpp index ff771e15..6d5bf2b6 100644 --- a/sunshine/process.cpp +++ b/sunshine/process.cpp @@ -21,8 +21,7 @@ namespace pt = boost::property_tree; proc_t proc; -template -void process_end(bp::child &proc, bp::group &proc_handle, const std::chrono::duration& rel_time) { +void process_end(bp::child &proc, bp::group &proc_handle) { if(!proc.running()) { return; } @@ -46,7 +45,7 @@ int proc_t::execute(const std::string &name) { auto it = _name_to_proc.find(name); // Ensure starting from a clean slate - _undo_pre_cmd(); + terminate(); if(it == std::end(_name_to_proc)) { std::cout << "Error: Couldn't find ["sv << name << ']' << std::endl; @@ -65,7 +64,7 @@ int proc_t::execute(const std::string &name) { std::error_code ec; //Executed when returning from function auto fg = util::fail_guard([&]() { - _undo_pre_cmd(); + terminate(); }); for(; _undo_it != std::end(proc.prep_cmds); ++_undo_it) { @@ -107,11 +106,11 @@ bool proc_t::running() { return _process.running(); } -void proc_t::_undo_pre_cmd() { +void proc_t::terminate() { std::error_code ec; // Ensure child process is terminated - process_end(_process, _process_handle, 10s); + process_end(_process, _process_handle); if(ec) { std::cout << "FATAL Error: System: "sv << ec.message() << std::endl; @@ -148,7 +147,7 @@ const std::unordered_map &proc_t::get_apps() const { } proc_t::~proc_t() { - _undo_pre_cmd(); + terminate(); } std::string_view::iterator find_match(std::string_view::iterator begin, std::string_view::iterator end) { diff --git a/sunshine/process.h b/sunshine/process.h index 14d43d7e..6c467737 100644 --- a/sunshine/process.h +++ b/sunshine/process.h @@ -57,9 +57,9 @@ public: ~proc_t(); const std::unordered_map &get_apps() const; -private: - void _undo_pre_cmd(); + void terminate(); +private: boost::process::environment _env; std::unordered_map _name_to_proc;