From 9f6a4856fefd5f7f721eb848ec9102462a2f6092 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 09:41:09 -0500 Subject: [PATCH 01/86] Assign name to certs when confirming PIN --- src/confighttp.cpp | 3 +- src/nvhttp.cpp | 46 ++++++++++++++++++++++++--- src/nvhttp.h | 2 +- src_assets/common/assets/web/pin.html | 7 ++-- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 2c7d3b21a39..cc571bf2b27 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -673,7 +673,8 @@ namespace confighttp { // TODO: Input Validation pt::read_json(ss, inputTree); std::string pin = inputTree.get("pin"); - outputTree.put("status", nvhttp::pin(pin)); + std::string name = inputTree.get("name"); + outputTree.put("status", nvhttp::pin(pin, name)); } catch (std::exception &e) { BOOST_LOG(warning) << "SavePin: "sv << e.what(); diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index bd00cb3a85c..34c693ddfb6 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -112,9 +112,15 @@ namespace nvhttp { std::string pkey; } conf_intern; + struct named_cert_t { + std::string name; + std::string cert; + }; + struct client_t { std::string uniqueID; std::vector certs; + std::vector named_certs; }; struct pair_session_t { @@ -195,7 +201,15 @@ namespace nvhttp { cert_node.put_value(cert); cert_nodes.push_back(std::make_pair(""s, cert_node)); } - node.add_child("certs"s, cert_nodes); + + pt::ptree named_cert_nodes; + for (auto &named_cert : client.named_certs) { + pt::ptree named_cert_node; + named_cert_node.put("name"s, named_cert.name); + named_cert_node.put("cert"s, named_cert.cert); + named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); + } + node.add_child("named_certs"s, named_cert_nodes); nodes.push_back(std::make_pair(""s, node)); } @@ -243,8 +257,21 @@ namespace nvhttp { client.uniqueID = uniqID; + // Import from old format for (auto &[_, el] : device_node.get_child("certs")) { - client.certs.emplace_back(el.get_value()); + named_cert_t named_cert; + named_cert.name = ""s; + named_cert.cert = el.get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); + } + + for (auto &[_, el] : device_node.get_child("named_certs")) { + named_cert_t named_cert; + named_cert.name = el.get_child("name").get_value(); + named_cert.cert = el.get_child("cert").get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); } } } @@ -560,15 +587,16 @@ namespace nvhttp { /** * @brief Compare the user supplied pin to the Moonlight pin. * @param pin The user supplied pin. + * @param name The user supplied name. * @return `true` if the pin is correct, `false` otherwise. * * EXAMPLES: * ```cpp - * bool pin_status = nvhttp::pin("1234"); + * bool pin_status = nvhttp::pin("1234", "laptop"); * ``` */ bool - pin(std::string pin) { + pin(std::string pin, std::string name) { pt::ptree tree; if (map_id_sess.empty()) { return false; @@ -594,6 +622,13 @@ namespace nvhttp { auto &sess = std::begin(map_id_sess)->second; getservercert(sess, tree, pin); + // set up named cert + auto &client = map_id_client[sess.client.uniqueID]; + named_cert_t named_cert; + named_cert.name = name; + named_cert.cert = sess.client.cert; + client.named_certs.emplace_back(named_cert); + // response to the request for pin std::ostringstream data; pt::write_xml(data, tree); @@ -970,6 +1005,9 @@ namespace nvhttp { for (auto &cert : client.certs) { cert_chain.add(crypto::x509(cert)); } + for (auto &named_cert : client.named_certs) { + cert_chain.add(crypto::x509(named_cert.cert)); + } } auto add_cert = std::make_shared>(30); diff --git a/src/nvhttp.h b/src/nvhttp.h index 3be24b3de06..0a5862514c4 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -43,7 +43,7 @@ namespace nvhttp { void start(); bool - pin(std::string pin); + pin(std::string pin, std::string name); void erase_all_clients(); } // namespace nvhttp diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index edb9b814a5d..fe18c49c66e 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -11,7 +11,8 @@

PIN Pairing

- + +
@@ -37,8 +38,9 @@

PIN Pairing

document.querySelector("#form").addEventListener("submit", (e) => { e.preventDefault(); let pin = document.querySelector("#pin-input").value; + let name = document.querySelector("#name-input").value; document.querySelector("#status").innerHTML = ""; - let b = JSON.stringify({ pin: pin }); + let b = JSON.stringify({ pin: pin, name: name }); fetch("/api/pin", { method: "POST", body: b }) .then((response) => response.json()) .then((response) => { @@ -47,6 +49,7 @@

PIN Pairing

"#status" ).innerHTML = ``; document.querySelector("#pin-input").value = ""; + document.querySelector("#name-input").value = ""; } else { document.querySelector( "#status" From ca6d1a28300a09598b3f02b457d84a242ddfbcc4 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:16:25 -0500 Subject: [PATCH 02/86] Don't prepare nodes for old format --- src/nvhttp.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 34c693ddfb6..94fa4e90191 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -195,13 +195,6 @@ namespace nvhttp { node.put("uniqueid"s, client.uniqueID); - pt::ptree cert_nodes; - for (auto &cert : client.certs) { - pt::ptree cert_node; - cert_node.put_value(cert); - cert_nodes.push_back(std::make_pair(""s, cert_node)); - } - pt::ptree named_cert_nodes; for (auto &named_cert : client.named_certs) { pt::ptree named_cert_node; From 567725d2d62ebc533a8b72022a0cc5ae08f9127d Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:17:22 -0500 Subject: [PATCH 03/86] Only read "certs" and "named_certs" if available --- src/nvhttp.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 94fa4e90191..f23a775f7eb 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -251,20 +251,24 @@ namespace nvhttp { client.uniqueID = uniqID; // Import from old format - for (auto &[_, el] : device_node.get_child("certs")) { - named_cert_t named_cert; - named_cert.name = ""s; - named_cert.cert = el.get_value(); - client.named_certs.emplace_back(named_cert); - client.certs.emplace_back(named_cert.cert); + if(device_node.count("certs")) { + for (auto &[_, el] : device_node.get_child("certs")) { + named_cert_t named_cert; + named_cert.name = ""s; + named_cert.cert = el.get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); + } } - for (auto &[_, el] : device_node.get_child("named_certs")) { - named_cert_t named_cert; - named_cert.name = el.get_child("name").get_value(); - named_cert.cert = el.get_child("cert").get_value(); - client.named_certs.emplace_back(named_cert); - client.certs.emplace_back(named_cert.cert); + if(device_node.count("named_certs")) { + for (auto &[_, el] : device_node.get_child("named_certs")) { + named_cert_t named_cert; + named_cert.name = el.get_child("name").get_value(); + named_cert.cert = el.get_child("cert").get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); + } } } } From 223fdfa6592b46674ba2f6668b841e8870ece65b Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:17:55 -0500 Subject: [PATCH 04/86] Generate and track uniqueID for named certs --- src/nvhttp.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index f23a775f7eb..663f59eecd3 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -114,6 +114,7 @@ namespace nvhttp { struct named_cert_t { std::string name; + std::string uniqueID; std::string cert; }; @@ -200,6 +201,7 @@ namespace nvhttp { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); + named_cert_node.put("uniqueID"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } node.add_child("named_certs"s, named_cert_nodes); @@ -256,6 +258,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = ""s; named_cert.cert = el.get_value(); + named_cert.uniqueID = uuid_util::uuid_t::generate().string(); client.named_certs.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } @@ -266,6 +269,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); named_cert.cert = el.get_child("cert").get_value(); + named_cert.uniqueID = el.get_child("uniqueID").get_value(); client.named_certs.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } @@ -624,6 +628,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = name; named_cert.cert = sess.client.cert; + named_cert.uniqueID = uuid_util::uuid_t::generate().string(); client.named_certs.emplace_back(named_cert); // response to the request for pin From 4b9f9d0c4eaed20d806743ca5c968fa42f300e65 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 21:57:41 -0500 Subject: [PATCH 05/86] API to list paired clients --- src/confighttp.cpp | 23 +++++++++++++++++++++++ src/nvhttp.cpp | 15 +++++++++++++++ src/nvhttp.h | 5 +++++ 3 files changed, 43 insertions(+) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index cc571bf2b27..44765d7ab3a 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -701,6 +701,28 @@ namespace confighttp { outputTree.put("status", true); } + void + listClients(resp_https_t response, req_https_t request) { + if (!authenticate(response, request)) return; + + print_req(request); + + pt::ptree named_certs = nvhttp::get_all_clients(); + + pt::ptree outputTree; + + outputTree.put("status", false); + + auto g = util::fail_guard([&]() { + std::ostringstream data; + pt::write_json(data, outputTree); + response->write(data.str()); + }); + + outputTree.add_child("named_certs", named_certs); + outputTree.put("status", true); + } + void closeApp(resp_https_t response, req_https_t request) { if (!authenticate(response, request)) return; @@ -746,6 +768,7 @@ namespace confighttp { server.resource["^/api/password$"]["POST"] = savePassword; server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; + server.resource["^/api/clients/list$"]["GET"] = listClients; server.resource["^/api/apps/close$"]["POST"] = closeApp; server.resource["^/api/covers/upload$"]["POST"] = uploadCover; server.resource["^/images/sunshine.ico$"]["GET"] = getFaviconImage; diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 663f59eecd3..382038b8682 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -752,6 +752,21 @@ namespace nvhttp { response->close_connection_after_response = true; } + pt::ptree + get_all_clients() { + pt::ptree named_cert_nodes; + for (auto &[_, client] : map_id_client) { + for (auto &named_cert : client.named_certs) { + pt::ptree named_cert_node; + named_cert_node.put("name"s, named_cert.name); + named_cert_node.put("uniqueID"s, named_cert.uniqueID); + named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); + } + } + + return named_cert_nodes; + } + void applist(resp_https_t response, req_https_t request) { print_req(request); diff --git a/src/nvhttp.h b/src/nvhttp.h index 0a5862514c4..11df8fc6f56 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -9,6 +9,9 @@ // standard includes #include +// lib includes +#include + // local includes #include "thread_safe.h" @@ -44,6 +47,8 @@ namespace nvhttp { start(); bool pin(std::string pin, std::string name); + boost::property_tree::ptree + get_all_clients(); void erase_all_clients(); } // namespace nvhttp From c8d74f21605edacaec8e2c015d185fcd3db3146a Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 21:59:35 -0500 Subject: [PATCH 06/86] API to unpair clients --- src/confighttp.cpp | 32 ++++++++++++++++++++++++++++++++ src/nvhttp.cpp | 23 +++++++++++++++++++++++ src/nvhttp.h | 2 ++ 3 files changed, 57 insertions(+) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 44765d7ab3a..29b7b010909 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -701,6 +701,37 @@ namespace confighttp { outputTree.put("status", true); } + void + unpairClient(resp_https_t response, req_https_t request) { + if (!authenticate(response, request)) return; + + print_req(request); + + std::stringstream ss; + ss << request->content.rdbuf(); + + pt::ptree inputTree, outputTree; + + auto g = util::fail_guard([&]() { + std::ostringstream data; + pt::write_json(data, outputTree); + response->write(data.str()); + }); + + try { + // TODO: Input Validation + pt::read_json(ss, inputTree); + std::string uniqueid = inputTree.get("uniqueid"); + outputTree.put("status", nvhttp::unpair_client(uniqueid)); + } + catch (std::exception &e) { + BOOST_LOG(warning) << "UnpairClient: "sv << e.what(); + outputTree.put("status", false); + outputTree.put("error", e.what()); + return; + } + } + void listClients(resp_https_t response, req_https_t request) { if (!authenticate(response, request)) return; @@ -769,6 +800,7 @@ namespace confighttp { server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; server.resource["^/api/clients/list$"]["GET"] = listClients; + server.resource["^/api/clients/unpair-single$"]["POST"] = unpairClient; server.resource["^/api/apps/close$"]["POST"] = closeApp; server.resource["^/api/covers/upload$"]["POST"] = uploadCover; server.resource["^/images/sunshine.ico$"]["GET"] = getFaviconImage; diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 382038b8682..1ac44cbe50c 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -1153,4 +1153,27 @@ namespace nvhttp { map_id_client.clear(); save_state(); } + + /** + * @brief Remove all single client. + * + * EXAMPLES: + * ```cpp + * nvhttp::unpair_client("4D7BB2DD-5704-A405-B41C-891A022932E1"); + * ``` + */ + bool + unpair_client(std::string uniqueID) { + for (auto &[_, client] : map_id_client) { + for (auto it = client.named_certs.begin(); it != client.named_certs.end();) + { + if ((*it).uniqueID == uniqueID) + it = client.named_certs.erase(it); + else + ++it; + } + } + save_state(); + return true; + } } // namespace nvhttp diff --git a/src/nvhttp.h b/src/nvhttp.h index 11df8fc6f56..f150bae14e1 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -47,6 +47,8 @@ namespace nvhttp { start(); bool pin(std::string pin, std::string name); + bool + unpair_client(std::string uniqueid); boost::property_tree::ptree get_all_clients(); void From 2e7655bfff677e9427b7b90cab0a237b4ee7e747 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 02:58:15 -0500 Subject: [PATCH 07/86] During unpairing, also remove cert from client.certs --- src/nvhttp.cpp | 29 ++++++++++++++++++++++------- src/nvhttp.h | 2 +- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 1ac44cbe50c..93f72edbdf2 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -1162,18 +1162,33 @@ namespace nvhttp { * nvhttp::unpair_client("4D7BB2DD-5704-A405-B41C-891A022932E1"); * ``` */ - bool + int unpair_client(std::string uniqueID) { + int removed = 0; for (auto &[_, client] : map_id_client) { - for (auto it = client.named_certs.begin(); it != client.named_certs.end();) - { - if ((*it).uniqueID == uniqueID) + for (auto it = client.named_certs.begin(); it != client.named_certs.end();) { + if ((*it).uniqueID == uniqueID) { + // Find matching cert and remove it + for (auto cert = client.certs.begin(); cert != client.certs.end();) { + if ((*cert) == (*it).cert) { + cert = client.certs.erase(cert); + removed++; + } + else { + ++cert; + } + } + + // And then remove the named cert it = client.named_certs.erase(it); - else + removed++; + } + else { ++it; - } + } + } } save_state(); - return true; + return removed; } } // namespace nvhttp diff --git a/src/nvhttp.h b/src/nvhttp.h index f150bae14e1..6fdf202ac29 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -47,7 +47,7 @@ namespace nvhttp { start(); bool pin(std::string pin, std::string name); - bool + int unpair_client(std::string uniqueid); boost::property_tree::ptree get_all_clients(); From b8f8b46b67460a4a16c42693cbdb05d59f9af58a Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 02:59:37 -0500 Subject: [PATCH 08/86] Added UI for unpairing individual clients --- src_assets/common/assets/web/pin.html | 50 +++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index fe18c49c66e..1bb3091b9e6 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -8,7 +8,7 @@
-

PIN Pairing

+

PIN Pairing

@@ -22,6 +22,19 @@

PIN Pairing

+
+
+
+

Paired Clients

+
Refresh
+
+
+
Success! Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions.
+ +
+
    +
    +
    @@ -55,6 +68,39 @@

    PIN Pairing

    "#status" ).innerHTML = ``; } + refreshClients(); }); }); - + + const clientList = document.querySelector("#client-list"); + + function refreshClients() { + fetch("/api/clients/list") + .then((response) => response.json()) + .then((response) => { + clientList.innerHTML = ""; + if (response.status === 'true' && response.named_certs && response.named_certs.length) { + for (const named_cert of response.named_certs) { + clientList.innerHTML += `
    ${named_cert.name != "" ? named_cert.name : "Unknown"}
    Remove
    `; + } + } else { + clientList.innerHTML = `

    There are no paired clients.

    `; + } + for (const unpairOption of clientList.querySelectorAll(".unpair")) { + unpairOption.addEventListener("click", () => { + fetch("/api/clients/unpair-single", { method: "POST", body: JSON.stringify({ uniqueid: unpairOption.dataset.uniqueid }) }).then(() => { + document.querySelector("#apply-alert").style.display = ""; + refreshClients(); + }); + }); + } + }); + } + refreshClients(); + + document.querySelector("#client-refresh").addEventListener("click", refreshClients); + document.querySelector("#apply-alert .apply").addEventListener("click", () => { + document.querySelector("#apply-alert").style.display = "none!important"; + fetch("/api/restart", { method: "POST" }); + }); + \ No newline at end of file From 73bda364113ec3080abe91b631a0d37a19b9c788 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 04:05:45 -0500 Subject: [PATCH 09/86] Formatting --- src/nvhttp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 93f72edbdf2..c44873dab88 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -253,7 +253,7 @@ namespace nvhttp { client.uniqueID = uniqID; // Import from old format - if(device_node.count("certs")) { + if (device_node.count("certs")) { for (auto &[_, el] : device_node.get_child("certs")) { named_cert_t named_cert; named_cert.name = ""s; @@ -264,7 +264,7 @@ namespace nvhttp { } } - if(device_node.count("named_certs")) { + if (device_node.count("named_certs")) { for (auto &[_, el] : device_node.get_child("named_certs")) { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); @@ -763,7 +763,7 @@ namespace nvhttp { named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } } - + return named_cert_nodes; } From bb3fd9a45eee3bae3f12e9dbdbd703f9e8d77297 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 04:16:48 -0500 Subject: [PATCH 10/86] Comment typo --- src/nvhttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index c44873dab88..a754c8ff7a5 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -1155,7 +1155,7 @@ namespace nvhttp { } /** - * @brief Remove all single client. + * @brief Remove single client. * * EXAMPLES: * ```cpp From 67988be12f00f1b6747c95521034bfc44583d7d5 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 04:43:14 -0500 Subject: [PATCH 11/86] Use lowercase property name for consistency --- src/nvhttp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index a754c8ff7a5..840d1fe3c56 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -201,7 +201,7 @@ namespace nvhttp { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); - named_cert_node.put("uniqueID"s, named_cert.uniqueID); + named_cert_node.put("uniqueid"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } node.add_child("named_certs"s, named_cert_nodes); @@ -269,7 +269,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); named_cert.cert = el.get_child("cert").get_value(); - named_cert.uniqueID = el.get_child("uniqueID").get_value(); + named_cert.uniqueID = el.get_child("uniqueid").get_value(); client.named_certs.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } From 8c8dfcff9aa0963565e0944105ed0c828718df09 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:23:40 -0500 Subject: [PATCH 12/86] Fixed "restart Sunshine" banner not hiding after clicking "apply" --- src_assets/common/assets/web/pin.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 1bb3091b9e6..24bee6aca5a 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -89,7 +89,7 @@

    Paired Clients

    for (const unpairOption of clientList.querySelectorAll(".unpair")) { unpairOption.addEventListener("click", () => { fetch("/api/clients/unpair-single", { method: "POST", body: JSON.stringify({ uniqueid: unpairOption.dataset.uniqueid }) }).then(() => { - document.querySelector("#apply-alert").style.display = ""; + document.querySelector("#apply-alert").style.setProperty('display', 'flex', 'important'); refreshClients(); }); }); @@ -100,7 +100,7 @@

    Paired Clients

    document.querySelector("#client-refresh").addEventListener("click", refreshClients); document.querySelector("#apply-alert .apply").addEventListener("click", () => { - document.querySelector("#apply-alert").style.display = "none!important"; + document.querySelector("#apply-alert").style.setProperty('display', 'none', 'important'); fetch("/api/restart", { method: "POST" }); }); \ No newline at end of file From b6010a6c8e1f65309e2d64124d6a7727667099fb Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:33:44 -0500 Subject: [PATCH 13/86] Update sunshine_state.json format to no longer use root.devices sunshine_state.json now follows the format outlined in https://github.com/LizardByte/Sunshine/pull/2042#issuecomment-1904634424 --- src/nvhttp.cpp | 70 +++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 7117d43b39d..9db6f602fe2 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -190,7 +190,6 @@ namespace nvhttp { root.erase("root"s); root.put("root.uniqueid", http::unique_id); - auto &nodes = root.add_child("root.devices", pt::ptree {}); for (auto &[_, client] : map_id_client) { pt::ptree node; @@ -201,12 +200,10 @@ namespace nvhttp { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); - named_cert_node.put("uniqueid"s, named_cert.uniqueID); + named_cert_node.put("uuid"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } - node.add_child("named_certs"s, named_cert_nodes); - - nodes.push_back(std::make_pair(""s, node)); + root.add_child("root.named_certs"s, named_cert_nodes); } try { @@ -226,9 +223,9 @@ namespace nvhttp { return; } - pt::ptree root; + pt::ptree tree; try { - pt::read_json(config::nvhttp.file_state, root); + pt::read_json(config::nvhttp.file_state, tree); } catch (std::exception &e) { BOOST_LOG(error) << "Couldn't read "sv << config::nvhttp.file_state << ": "sv << e.what(); @@ -236,7 +233,7 @@ namespace nvhttp { return; } - auto unique_id_p = root.get_optional("root.uniqueid"); + auto unique_id_p = tree.get_optional("root.uniqueid"); if (!unique_id_p) { // This file doesn't contain moonlight credentials http::unique_id = uuid_util::uuid_t::generate().string(); @@ -244,35 +241,38 @@ namespace nvhttp { } http::unique_id = std::move(*unique_id_p); - auto device_nodes = root.get_child("root.devices"); - - for (auto &[_, device_node] : device_nodes) { - auto uniqID = device_node.get("uniqueid"); - auto &client = map_id_client.emplace(uniqID, client_t {}).first->second; - - client.uniqueID = uniqID; - - // Import from old format - if (device_node.count("certs")) { - for (auto &[_, el] : device_node.get_child("certs")) { - named_cert_t named_cert; - named_cert.name = ""s; - named_cert.cert = el.get_value(); - named_cert.uniqueID = uuid_util::uuid_t::generate().string(); - client.named_certs.emplace_back(named_cert); - client.certs.emplace_back(named_cert.cert); + auto root = tree.get_child("root"); + auto &client = map_id_client.emplace("0123456789ABCDEF"s, client_t {}).first->second; + client.uniqueID = "0123456789ABCDEF"s; + + // Import from old format + if(root.get_child_optional("devices")) { + auto device_nodes = root.get_child("devices"); + for (auto &[_, device_node] : device_nodes) { + auto uniqID = device_node.get("uniqueid"); + + if (device_node.count("certs")) { + for (auto &[_, el] : device_node.get_child("certs")) { + named_cert_t named_cert; + named_cert.name = ""s; + named_cert.cert = el.get_value(); + named_cert.uniqueID = uuid_util::uuid_t::generate().string(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); + } } } - - if (device_node.count("named_certs")) { - for (auto &[_, el] : device_node.get_child("named_certs")) { - named_cert_t named_cert; - named_cert.name = el.get_child("name").get_value(); - named_cert.cert = el.get_child("cert").get_value(); - named_cert.uniqueID = el.get_child("uniqueid").get_value(); - client.named_certs.emplace_back(named_cert); - client.certs.emplace_back(named_cert.cert); - } + } + + + if (root.count("named_certs")) { + for (auto &[_, el] : root.get_child("named_certs")) { + named_cert_t named_cert; + named_cert.name = el.get_child("name").get_value(); + named_cert.cert = el.get_child("cert").get_value(); + named_cert.uniqueID = el.get_child("uuid").get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); } } } From 6c639920b6f09f2a997ae4e7f20bf6a6d39641e0 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:37:47 -0500 Subject: [PATCH 14/86] Formatting --- src/nvhttp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 9db6f602fe2..e2091fbeb80 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -246,8 +246,8 @@ namespace nvhttp { client.uniqueID = "0123456789ABCDEF"s; // Import from old format - if(root.get_child_optional("devices")) { - auto device_nodes = root.get_child("devices"); + if (root.get_child_optional("devices")) { + auto device_nodes = root.get_child("devices"); for (auto &[_, device_node] : device_nodes) { auto uniqID = device_node.get("uniqueid"); From d842e97cd9469c92e30a1eb0f02f901673f21700 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:46:39 -0500 Subject: [PATCH 15/86] Formatting --- src/nvhttp.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index e2091fbeb80..bc22851e5a3 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -262,9 +262,8 @@ namespace nvhttp { } } } - } + } - if (root.count("named_certs")) { for (auto &[_, el] : root.get_child("named_certs")) { named_cert_t named_cert; From 541e341ccd34990e8ec7064a2fc6d209ea4d09bb Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 17:11:26 -0500 Subject: [PATCH 16/86] Refactor map_id_client into a single client_t --- src/nvhttp.cpp | 110 +++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 54 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index bc22851e5a3..1a5eba07644 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -147,7 +147,7 @@ namespace nvhttp { // uniqueID, session std::unordered_map map_id_sess; - std::unordered_map map_id_client; + client_t client_root; using args_t = SimpleWeb::CaseInsensitiveMultimap; using resp_https_t = std::shared_ptr::Response>; @@ -190,21 +190,20 @@ namespace nvhttp { root.erase("root"s); root.put("root.uniqueid", http::unique_id); - for (auto &[_, client] : map_id_client) { - pt::ptree node; - - node.put("uniqueid"s, client.uniqueID); - - pt::ptree named_cert_nodes; - for (auto &named_cert : client.named_certs) { - pt::ptree named_cert_node; - named_cert_node.put("name"s, named_cert.name); - named_cert_node.put("cert"s, named_cert.cert); - named_cert_node.put("uuid"s, named_cert.uniqueID); - named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); - } - root.add_child("root.named_certs"s, named_cert_nodes); + client_t &client = client_root; + pt::ptree node; + + node.put("uniqueid"s, client.uniqueID); + + pt::ptree named_cert_nodes; + for (auto &named_cert : client.named_certs) { + pt::ptree named_cert_node; + named_cert_node.put("name"s, named_cert.name); + named_cert_node.put("cert"s, named_cert.cert); + named_cert_node.put("uuid"s, named_cert.uniqueID); + named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } + root.add_child("root.named_certs"s, named_cert_nodes); try { pt::write_json(config::nvhttp.file_state, root); @@ -242,7 +241,7 @@ namespace nvhttp { http::unique_id = std::move(*unique_id_p); auto root = tree.get_child("root"); - auto &client = map_id_client.emplace("0123456789ABCDEF"s, client_t {}).first->second; + client_t client; client.uniqueID = "0123456789ABCDEF"s; // Import from old format @@ -274,18 +273,21 @@ namespace nvhttp { client.certs.emplace_back(named_cert.cert); } } + client_root = client; } void update_id_client(const std::string &uniqueID, std::string &&cert, op_e op) { switch (op) { case op_e::ADD: { - auto &client = map_id_client[uniqueID]; + client_t &client = client_root; client.certs.emplace_back(std::move(cert)); client.uniqueID = uniqueID; } break; case op_e::REMOVE: - map_id_client.erase(uniqueID); + client_t client; + client.uniqueID = uniqueID; + client_root = client; break; } @@ -624,7 +626,7 @@ namespace nvhttp { getservercert(sess, tree, pin); // set up named cert - auto &client = map_id_client[sess.client.uniqueID]; + client_t &client = client_root; named_cert_t named_cert; named_cert.name = name; named_cert.cert = sess.client.cert; @@ -663,7 +665,7 @@ namespace nvhttp { auto clientID = args.find("uniqueid"s); if (clientID != std::end(args)) { - if (auto it = map_id_client.find(clientID->second); it != std::end(map_id_client)) { + if (client_root.uniqueID == clientID->second) { pair_status = 1; } } @@ -755,13 +757,12 @@ namespace nvhttp { pt::ptree get_all_clients() { pt::ptree named_cert_nodes; - for (auto &[_, client] : map_id_client) { - for (auto &named_cert : client.named_certs) { - pt::ptree named_cert_node; - named_cert_node.put("name"s, named_cert.name); - named_cert_node.put("uniqueID"s, named_cert.uniqueID); - named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); - } + client_t &client = client_root; + for (auto &named_cert : client.named_certs) { + pt::ptree named_cert_node; + named_cert_node.put("name"s, named_cert.name); + named_cert_node.put("uniqueID"s, named_cert.uniqueID); + named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } return named_cert_nodes; @@ -1018,13 +1019,12 @@ namespace nvhttp { conf_intern.servercert = read_file(config::nvhttp.cert.c_str()); crypto::cert_chain_t cert_chain; - for (auto &[_, client] : map_id_client) { - for (auto &cert : client.certs) { - cert_chain.add(crypto::x509(cert)); - } - for (auto &named_cert : client.named_certs) { - cert_chain.add(crypto::x509(named_cert.cert)); - } + client_t &client = client_root; + for (auto &cert : client.certs) { + cert_chain.add(crypto::x509(cert)); + } + for (auto &named_cert : client.named_certs) { + cert_chain.add(crypto::x509(named_cert.cert)); } auto add_cert = std::make_shared>(30); @@ -1150,7 +1150,9 @@ namespace nvhttp { */ void erase_all_clients() { - map_id_client.clear(); + client_t client; + client.uniqueID = "0123456789ABCDEF"s; + client_root = client; save_state(); } @@ -1165,29 +1167,29 @@ namespace nvhttp { int unpair_client(std::string uniqueID) { int removed = 0; - for (auto &[_, client] : map_id_client) { - for (auto it = client.named_certs.begin(); it != client.named_certs.end();) { - if ((*it).uniqueID == uniqueID) { - // Find matching cert and remove it - for (auto cert = client.certs.begin(); cert != client.certs.end();) { - if ((*cert) == (*it).cert) { - cert = client.certs.erase(cert); - removed++; - } - else { - ++cert; - } + client_t &client = client_root; + for (auto it = client.named_certs.begin(); it != client.named_certs.end();) { + if ((*it).uniqueID == uniqueID) { + // Find matching cert and remove it + for (auto cert = client.certs.begin(); cert != client.certs.end();) { + if ((*cert) == (*it).cert) { + cert = client.certs.erase(cert); + removed++; + } + else { + ++cert; } - - // And then remove the named cert - it = client.named_certs.erase(it); - removed++; - } - else { - ++it; } + + // And then remove the named cert + it = client.named_certs.erase(it); + removed++; + } + else { + ++it; } } + save_state(); return removed; } From 5cc7fc0d1376497787c76dff4420e0ab7b593d86 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 17:17:10 -0500 Subject: [PATCH 17/86] Rename named_certs to named_devices --- src/nvhttp.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 1a5eba07644..f54aec24d3f 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -121,7 +121,7 @@ namespace nvhttp { struct client_t { std::string uniqueID; std::vector certs; - std::vector named_certs; + std::vector named_devices; }; struct pair_session_t { @@ -196,14 +196,14 @@ namespace nvhttp { node.put("uniqueid"s, client.uniqueID); pt::ptree named_cert_nodes; - for (auto &named_cert : client.named_certs) { + for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); named_cert_node.put("uuid"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } - root.add_child("root.named_certs"s, named_cert_nodes); + root.add_child("root.named_devices"s, named_cert_nodes); try { pt::write_json(config::nvhttp.file_state, root); @@ -256,20 +256,20 @@ namespace nvhttp { named_cert.name = ""s; named_cert.cert = el.get_value(); named_cert.uniqueID = uuid_util::uuid_t::generate().string(); - client.named_certs.emplace_back(named_cert); + client.named_devices.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } } } } - if (root.count("named_certs")) { - for (auto &[_, el] : root.get_child("named_certs")) { + if (root.count("named_devices")) { + for (auto &[_, el] : root.get_child("named_devices")) { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); named_cert.cert = el.get_child("cert").get_value(); named_cert.uniqueID = el.get_child("uuid").get_value(); - client.named_certs.emplace_back(named_cert); + client.named_devices.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } } @@ -631,7 +631,7 @@ namespace nvhttp { named_cert.name = name; named_cert.cert = sess.client.cert; named_cert.uniqueID = uuid_util::uuid_t::generate().string(); - client.named_certs.emplace_back(named_cert); + client.named_devices.emplace_back(named_cert); // response to the request for pin std::ostringstream data; @@ -758,7 +758,7 @@ namespace nvhttp { get_all_clients() { pt::ptree named_cert_nodes; client_t &client = client_root; - for (auto &named_cert : client.named_certs) { + for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("uniqueID"s, named_cert.uniqueID); @@ -1023,7 +1023,7 @@ namespace nvhttp { for (auto &cert : client.certs) { cert_chain.add(crypto::x509(cert)); } - for (auto &named_cert : client.named_certs) { + for (auto &named_cert : client.named_devices) { cert_chain.add(crypto::x509(named_cert.cert)); } @@ -1168,7 +1168,7 @@ namespace nvhttp { unpair_client(std::string uniqueID) { int removed = 0; client_t &client = client_root; - for (auto it = client.named_certs.begin(); it != client.named_certs.end();) { + for (auto it = client.named_devices.begin(); it != client.named_devices.end();) { if ((*it).uniqueID == uniqueID) { // Find matching cert and remove it for (auto cert = client.certs.begin(); cert != client.certs.end();) { @@ -1182,7 +1182,7 @@ namespace nvhttp { } // And then remove the named cert - it = client.named_certs.erase(it); + it = client.named_devices.erase(it); removed++; } else { From 0e1c02b069707df4a3fd9a855b9e86afe4343a64 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 21:20:11 -0500 Subject: [PATCH 18/86] Update API to use uuid instead of uniqueid for clients --- src/confighttp.cpp | 4 ++-- src/nvhttp.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 29b7b010909..56a9114fbb3 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -721,8 +721,8 @@ namespace confighttp { try { // TODO: Input Validation pt::read_json(ss, inputTree); - std::string uniqueid = inputTree.get("uniqueid"); - outputTree.put("status", nvhttp::unpair_client(uniqueid)); + std::string uuid = inputTree.get("uuid"); + outputTree.put("status", nvhttp::unpair_client(uuid)); } catch (std::exception &e) { BOOST_LOG(warning) << "UnpairClient: "sv << e.what(); diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index f54aec24d3f..63693b231c0 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -761,7 +761,7 @@ namespace nvhttp { for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); - named_cert_node.put("uniqueID"s, named_cert.uniqueID); + named_cert_node.put("uuid"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } From 3f4fc1c4f5eaa57b5f860b37dcf3d5523fb03c6e Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 21:36:25 -0500 Subject: [PATCH 19/86] Move Paired Client UI to Troubleshooting page --- src_assets/common/assets/web/pin.html | 46 ------------ .../common/assets/web/troubleshooting.html | 73 +++++++++++++++---- 2 files changed, 58 insertions(+), 61 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 24bee6aca5a..1bf1c583917 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -22,19 +22,6 @@

    PIN Pairing

    -
    -
    -
    -

    Paired Clients

    -
    Refresh
    -
    -
    -
    Success! Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions.
    - -
    -
      -
      -
      @@ -68,39 +55,6 @@

      Paired Clients

      "#status" ).innerHTML = ``; } - refreshClients(); }); }); - - const clientList = document.querySelector("#client-list"); - - function refreshClients() { - fetch("/api/clients/list") - .then((response) => response.json()) - .then((response) => { - clientList.innerHTML = ""; - if (response.status === 'true' && response.named_certs && response.named_certs.length) { - for (const named_cert of response.named_certs) { - clientList.innerHTML += `
      ${named_cert.name != "" ? named_cert.name : "Unknown"}
      Remove
      `; - } - } else { - clientList.innerHTML = `

      There are no paired clients.

      `; - } - for (const unpairOption of clientList.querySelectorAll(".unpair")) { - unpairOption.addEventListener("click", () => { - fetch("/api/clients/unpair-single", { method: "POST", body: JSON.stringify({ uniqueid: unpairOption.dataset.uniqueid }) }).then(() => { - document.querySelector("#apply-alert").style.setProperty('display', 'flex', 'important'); - refreshClients(); - }); - }); - } - }); - } - refreshClients(); - - document.querySelector("#client-refresh").addEventListener("click", refreshClients); - document.querySelector("#apply-alert .apply").addEventListener("click", () => { - document.querySelector("#apply-alert").style.setProperty('display', 'none', 'important'); - fetch("/api/restart", { method: "POST" }); - }); \ No newline at end of file diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 6ad8afc59da..50e7f54d257 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -82,23 +82,38 @@

      Restart Sunshine

      -
      +
      -

      Unpair All Clients

      -
      -

      Remove all your paired devices

      -
      - Unpair Successful! -
      -
      - Error while unpairing -
      -
      - +
      +
      +

      Unpair Clients

      + +
      +
      +
      Success! Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions.
      + +
      +
      + Unpair Successful! +
      +
      + Error while unpairing +
      +
      +

      Remove your paired devices.

      +
        +
        +
        {{client.name != "" ? client.name : "Unknown Client"}}
        +
        +
      +
        +
        There are no paired clients.
        +
      +
      @@ -119,7 +134,7 @@

      Logs

      \ No newline at end of file + From dd6b59739764a9dbd47f4a0def0d70ea25f43c55 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:18:51 -0500 Subject: [PATCH 21/86] Update src_assets/common/assets/web/troubleshooting.html Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/troubleshooting.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 50e7f54d257..88daff1e2f2 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -86,7 +86,7 @@

      Restart Sunshine

      -

      Unpair Clients

      +

      Unpair Clients

      From 3a1c109ad870a7f1bddf916c93211862cca07e9c Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:03 -0500 Subject: [PATCH 22/86] Update src/confighttp.cpp Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src/confighttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 56a9114fbb3..e0e44b84b42 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -800,7 +800,7 @@ namespace confighttp { server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; server.resource["^/api/clients/list$"]["GET"] = listClients; - server.resource["^/api/clients/unpair-single$"]["POST"] = unpairClient; + server.resource["^/api/clients/unpair$"]["POST"] = unpair; server.resource["^/api/apps/close$"]["POST"] = closeApp; server.resource["^/api/covers/upload$"]["POST"] = uploadCover; server.resource["^/images/sunshine.ico$"]["GET"] = getFaviconImage; From cb6846eaa9e88e5b87da4df72923d92aaba7e42b Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:25 -0500 Subject: [PATCH 23/86] Update src/confighttp.cpp Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src/confighttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index e0e44b84b42..f3135d0e2d9 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -702,7 +702,7 @@ namespace confighttp { } void - unpairClient(resp_https_t response, req_https_t request) { + unpair(resp_https_t response, req_https_t request) { if (!authenticate(response, request)) return; print_req(request); From 805311bd672692bea36e7a90fa71556610855a86 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:36 -0500 Subject: [PATCH 24/86] Update src/confighttp.cpp Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src/confighttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index f3135d0e2d9..8f2c38a98a7 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -725,7 +725,7 @@ namespace confighttp { outputTree.put("status", nvhttp::unpair_client(uuid)); } catch (std::exception &e) { - BOOST_LOG(warning) << "UnpairClient: "sv << e.what(); + BOOST_LOG(warning) << "Unpair: "sv << e.what(); outputTree.put("status", false); outputTree.put("error", e.what()); return; From a4a4125d10e3992d5ce5e6c93f14fbceefc23799 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:46 -0500 Subject: [PATCH 25/86] Update src/confighttp.cpp Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src/confighttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 8f2c38a98a7..61331d1fc57 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -798,7 +798,7 @@ namespace confighttp { server.resource["^/api/restart$"]["POST"] = restart; server.resource["^/api/password$"]["POST"] = savePassword; server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; - server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; + server.resource["^/api/clients/unpair-all$"]["POST"] = unpairAll; server.resource["^/api/clients/list$"]["GET"] = listClients; server.resource["^/api/clients/unpair$"]["POST"] = unpair; server.resource["^/api/apps/close$"]["POST"] = closeApp; From 60e2da7d5f95c2ce417cf3ecf416e6d18701013d Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:59 -0500 Subject: [PATCH 26/86] Update src_assets/common/assets/web/troubleshooting.html Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/troubleshooting.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 88daff1e2f2..111f9d02c67 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -195,7 +195,7 @@

      Logs

      }, unpairAll() { this.unpairAllPressed = true; - fetch("/api/clients/unpair", { method: "POST" }) + fetch("/api/clients/unpair-all", { method: "POST" }) .then((r) => r.json()) .then((r) => { this.showApplyMessage = true; From b5d7da4590dca11e269b3490d7bfee71fec56929 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:42:18 -0500 Subject: [PATCH 27/86] Update src_assets/common/assets/web/troubleshooting.html Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/troubleshooting.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 111f9d02c67..f45ed7cedab 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -207,7 +207,7 @@

      Logs

      }); }, unpairSingle(uuid) { - fetch("/api/clients/unpair-single", { method: "POST", body: JSON.stringify({ uuid }) }).then(() => { + fetch("/api/clients/unpair", { method: "POST", body: JSON.stringify({ uuid }) }).then(() => { this.showApplyMessage = true; this.refreshClients(); }); From fbd26d0a386d197d8d7ba9472ddad151212ae599 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sun, 28 Jan 2024 11:10:17 -0500 Subject: [PATCH 28/86] Rename device name field and mark fields as required https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-1845012932 --- src_assets/common/assets/web/pin.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index be4af0c22da..12da3eaf5e6 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -11,8 +11,8 @@

      PIN Pairing

      - - + +
      From 5ff80ada0b93dd8527c0c7e20e42e9f75065b0f3 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 10 Feb 2024 17:53:05 -0500 Subject: [PATCH 29/86] Remove uniqueID from client_t --- src/nvhttp.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 63693b231c0..fe921c4b7aa 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -119,7 +119,6 @@ namespace nvhttp { }; struct client_t { - std::string uniqueID; std::vector certs; std::vector named_devices; }; @@ -193,8 +192,6 @@ namespace nvhttp { client_t &client = client_root; pt::ptree node; - node.put("uniqueid"s, client.uniqueID); - pt::ptree named_cert_nodes; for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; @@ -242,7 +239,6 @@ namespace nvhttp { auto root = tree.get_child("root"); client_t client; - client.uniqueID = "0123456789ABCDEF"s; // Import from old format if (root.get_child_optional("devices")) { @@ -282,11 +278,9 @@ namespace nvhttp { case op_e::ADD: { client_t &client = client_root; client.certs.emplace_back(std::move(cert)); - client.uniqueID = uniqueID; } break; case op_e::REMOVE: client_t client; - client.uniqueID = uniqueID; client_root = client; break; } @@ -665,9 +659,7 @@ namespace nvhttp { auto clientID = args.find("uniqueid"s); if (clientID != std::end(args)) { - if (client_root.uniqueID == clientID->second) { - pair_status = 1; - } + pair_status = 1; } } @@ -1151,7 +1143,6 @@ namespace nvhttp { void erase_all_clients() { client_t client; - client.uniqueID = "0123456789ABCDEF"s; client_root = client; save_state(); } From 735d788f187f8d74db913203a4fcea7cb375e4bf Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 10 Feb 2024 18:09:49 -0500 Subject: [PATCH 30/86] Update named_cert_t to better match sunshine_state.json --- src/nvhttp.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index fe921c4b7aa..738e7a47688 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -114,7 +114,7 @@ namespace nvhttp { struct named_cert_t { std::string name; - std::string uniqueID; + std::string uuid; std::string cert; }; @@ -197,7 +197,7 @@ namespace nvhttp { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); - named_cert_node.put("uuid"s, named_cert.uniqueID); + named_cert_node.put("uuid"s, named_cert.uuid); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } root.add_child("root.named_devices"s, named_cert_nodes); @@ -251,7 +251,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = ""s; named_cert.cert = el.get_value(); - named_cert.uniqueID = uuid_util::uuid_t::generate().string(); + named_cert.uuid = uuid_util::uuid_t::generate().string(); client.named_devices.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } @@ -264,7 +264,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); named_cert.cert = el.get_child("cert").get_value(); - named_cert.uniqueID = el.get_child("uuid").get_value(); + named_cert.uuid = el.get_child("uuid").get_value(); client.named_devices.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } @@ -624,7 +624,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = name; named_cert.cert = sess.client.cert; - named_cert.uniqueID = uuid_util::uuid_t::generate().string(); + named_cert.uuid = uuid_util::uuid_t::generate().string(); client.named_devices.emplace_back(named_cert); // response to the request for pin @@ -753,7 +753,7 @@ namespace nvhttp { for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); - named_cert_node.put("uuid"s, named_cert.uniqueID); + named_cert_node.put("uuid"s, named_cert.uuid); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } @@ -1156,11 +1156,11 @@ namespace nvhttp { * ``` */ int - unpair_client(std::string uniqueID) { + unpair_client(std::string uuid) { int removed = 0; client_t &client = client_root; for (auto it = client.named_devices.begin(); it != client.named_devices.end();) { - if ((*it).uniqueID == uniqueID) { + if ((*it).uuid == uuid) { // Find matching cert and remove it for (auto cert = client.certs.begin(); cert != client.certs.end();) { if ((*cert) == (*it).cert) { From 5ef7b03f1b8226d213f98063f375cc03934b153a Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:41:14 -0400 Subject: [PATCH 31/86] Update web UI to use localization for single device pairing/unpairing --- src_assets/common/assets/web/pin.html | 6 ++--- .../assets/web/public/assets/locale/en.json | 11 ++++++--- .../common/assets/web/troubleshooting.html | 23 ++++++++----------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 2418c9682b7..1b3c6482285 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -8,11 +8,11 @@
      -

      {{ $t('pin.pin_pairing') }}

      +

      {{ $t('pin.pin_pairing') }}

      - - + +
      diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index f36b984c24e..8013bb914a7 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -6,6 +6,7 @@ "cancel": "Cancel", "disabled": "Disabled", "disabled_def": "Disabled (default)", + "dismiss": "Dismiss", "do_cmd": "Do Command", "elevated": "Elevated", "enabled": "Enabled", @@ -336,6 +337,7 @@ "success_msg": "Password has been changed successfully! This page will reload soon, your browser will ask you for the new credentials." }, "pin": { + "device_name": "Device Name", "pair_failure": "Pairing Failed: Check if the PIN is typed correctly", "pair_success": "Success! Please check Moonlight to continue", "pin_pairing": "PIN Pairing", @@ -364,10 +366,13 @@ "restart_sunshine_desc": "If Sunshine isn't working properly, you can try restarting it. This will terminate any running sessions.", "restart_sunshine_success": "Sunshine is restarting", "troubleshooting": "Troubleshooting", - "unpair_all": "Unpair All", - "unpair_all_desc": "Remove all your paired devices", + "unpair_all": "Unpair Devices", + "unpair_all_desc": "Remove your paired devices. Unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_all_error": "Error while unpairing", - "unpair_all_success": "Unpair Successful!" + "unpair_all_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", + "unpair_single_no_devices": "There are no paired devices.", + "unpair_single_unknown": "Unknown Client", + "unpair_title": "Unpair Devices" }, "welcome": { "confirm_password": "Confirm password", diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 0d75ec3187d..df3c8eafbb3 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -75,37 +75,34 @@

      {{ $t('troubleshooting.restart_sunshine') }}

      - +
      -

      {{ $t('troubleshooting.unpair_all') }}

      +

      {{ $t('troubleshooting.unpair_title') }}

      +
      +

      {{ $t('troubleshooting.unpair_all_desc') }}

      -
      Success! Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions.
      - -
      -
      - {{ $t('troubleshooting.unpair_all_success') }} +
      {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_all_success') }}
      +
      {{ $t('troubleshooting.unpair_all_error') }}
      -
      -

      {{ $t('troubleshooting.unpair_all_desc') }}

        -
        {{client.name != "" ? client.name : "Unknown Client"}}
        +
        {{client.name != "" ? client.name : $t('troubleshooting.unpair_single_unknown')}}
        -
        There are no paired clients.
        +
        {{ $t('troubleshooting.unpair_single_no_devices') }}
      @@ -199,6 +196,7 @@

      {{ $t('troubleshooting.logs') }}

      setTimeout(() => { this.unpairAllStatus = null; }, 5000); + this.refreshClients(); }); }, unpairSingle(uuid) { @@ -221,9 +219,6 @@

      {{ $t('troubleshooting.logs') }}

      }, clickedApplyBanner() { this.showApplyMessage = false; - fetch("/api/restart", { - method: "POST", - }); }, copyLogs() { navigator.clipboard.writeText(this.actualLogs); From cef0b19614f62acd286b632897840770bc22c2eb Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:42:45 -0400 Subject: [PATCH 32/86] Refresh client certs after unpairing a single client --- src/nvhttp.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 7bff07c6115..8857ce89772 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -274,6 +274,17 @@ namespace nvhttp { client.certs.emplace_back(named_cert.cert); } } + + + // Empty certificate chain and import certs from file + cert_chain.clear(); + for (auto &cert : client.certs) { + cert_chain.add(crypto::x509(cert)); + } + for (auto &named_cert : client.named_devices) { + cert_chain.add(crypto::x509(named_cert.cert)); + } + client_root = client; } @@ -1063,14 +1074,6 @@ namespace nvhttp { conf_intern.pkey = file_handler::read_file(config::nvhttp.pkey.c_str()); conf_intern.servercert = file_handler::read_file(config::nvhttp.cert.c_str()); - client_t &client = client_root; - for (auto &cert : client.certs) { - cert_chain.add(crypto::x509(cert)); - } - for (auto &named_cert : client.named_devices) { - cert_chain.add(crypto::x509(named_cert.cert)); - } - auto add_cert = std::make_shared>(30); // resume doesn't always get the parameter "localAudioPlayMode" @@ -1235,6 +1238,7 @@ namespace nvhttp { } save_state(); + load_state(); return removed; } } // namespace nvhttp From 4e7785480e3026a10db334bb78cd50d9d118ff51 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:45:22 -0400 Subject: [PATCH 33/86] Rename unpair all button --- src_assets/common/assets/web/public/assets/locale/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 8013bb914a7..5cabe6ee683 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -366,7 +366,7 @@ "restart_sunshine_desc": "If Sunshine isn't working properly, you can try restarting it. This will terminate any running sessions.", "restart_sunshine_success": "Sunshine is restarting", "troubleshooting": "Troubleshooting", - "unpair_all": "Unpair Devices", + "unpair_all": "Unpair All", "unpair_all_desc": "Remove your paired devices. Unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_all_error": "Error while unpairing", "unpair_all_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", From 270015244e8801ca59baab2ebe93649cd5f414c2 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 13:04:20 -0400 Subject: [PATCH 34/86] Formatting --- src/nvhttp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 8857ce89772..15b9d29ef25 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -274,7 +274,6 @@ namespace nvhttp { client.certs.emplace_back(named_cert.cert); } } - // Empty certificate chain and import certs from file cert_chain.clear(); From 1b6a828b1cdcda2854097b2d5788ee1d48f9dff9 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:13:02 -0400 Subject: [PATCH 35/86] Close session when unpairing all clients https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-2007534088 --- src/confighttp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 4ef0af75f6f..a237c1fc3a7 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -718,6 +718,7 @@ namespace confighttp { response->write(data.str()); }); nvhttp::erase_all_clients(); + proc::proc.terminate(); outputTree.put("status", true); } From 2e825370b93bf3c4667684905c3aad7b87c93e9c Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:14:05 -0400 Subject: [PATCH 36/86] Localize "PIN" input placeholder https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-2007515774 --- src_assets/common/assets/web/pin.html | 2 +- src_assets/common/assets/web/public/assets/locale/en.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 1b3c6482285..82bbcd7c426 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -11,7 +11,7 @@

      {{ $t('pin.pin_pairing') }}

      - +
      diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 5cabe6ee683..a4fb9a1ffd5 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -340,6 +340,7 @@ "device_name": "Device Name", "pair_failure": "Pairing Failed: Check if the PIN is typed correctly", "pair_success": "Success! Please check Moonlight to continue", + "pin": "PIN", "pin_pairing": "PIN Pairing", "send": "Send", "warning_msg": "Make sure you have access to the client you are pairing with. This software can give total control to your computer, so be careful!" From bb3c0ba03326aa8e1991a51dc6eeee94131c3112 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:21:35 -0400 Subject: [PATCH 37/86] Sort client list alphabetically https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-2007515774 --- src_assets/common/assets/web/troubleshooting.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index df3c8eafbb3..249924e3f1b 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -211,7 +211,9 @@

      {{ $t('troubleshooting.logs') }}

      .then((response) => { const clientList = document.querySelector("#client-list"); if (response.status === 'true' && response.named_certs && response.named_certs.length) { - this.clients = response.named_certs; + this.clients = response.named_certs.sort((a, b) => { + return (a.name.toLowerCase() > b.name.toLowerCase() || a.name == "" ? 1 : -1) + }); } else { this.clients = []; } From 31c1f214406ee7fda1eba073d34eb2912b93b11d Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:29:34 -0400 Subject: [PATCH 38/86] Specify that only individual unpair requires force close --- src_assets/common/assets/web/public/assets/locale/en.json | 5 +++-- src_assets/common/assets/web/troubleshooting.html | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index a4fb9a1ffd5..83f43b6f5f0 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -368,10 +368,11 @@ "restart_sunshine_success": "Sunshine is restarting", "troubleshooting": "Troubleshooting", "unpair_all": "Unpair All", - "unpair_all_desc": "Remove your paired devices. Unpaired devices with an active session will remain connected, but cannot start or resume a session.", + "unpair_all_desc": "Remove your paired devices. Individually unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_all_error": "Error while unpairing", - "unpair_all_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", + "unpair_all_success": "All devices unpaired.", "unpair_single_no_devices": "There are no paired devices.", + "unpair_single_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", "unpair_single_unknown": "Unknown Client", "unpair_title": "Unpair Devices" }, diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 249924e3f1b..3e945b9eaf8 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -88,10 +88,13 @@

      {{ $t('troubleshooting.unpair_title'

      {{ $t('troubleshooting.unpair_all_desc') }}

      -
      {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_all_success') }}
      +
      {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_single_success') }}
      -
      +
      + {{ $t('troubleshooting.unpair_all_success') }} +
      +
      {{ $t('troubleshooting.unpair_all_error') }}
      @@ -190,7 +193,6 @@

      {{ $t('troubleshooting.logs') }}

      fetch("/api/clients/unpair-all", { method: "POST" }) .then((r) => r.json()) .then((r) => { - this.showApplyMessage = true; this.unpairAllPressed = false; this.unpairAllStatus = r.status.toString() === "true"; setTimeout(() => { From 63d58758a3c8edeaaed0c38a2eeeecb534d22f8a Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:32:27 -0400 Subject: [PATCH 39/86] Reordered Vue page vars https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-2007515774 --- src_assets/common/assets/web/troubleshooting.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 3e945b9eaf8..260c77b82f7 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -138,16 +138,16 @@

      {{ $t('troubleshooting.logs') }}

      }, data() { return { + clients: [], closeAppPressed: false, closeAppStatus: null, + logs: 'Loading...', + logFilter: null, + logInterval: null, unpairAllPressed: false, unpairAllStatus: null, restartPressed: false, showApplyMessage: false, - clients: [], - logs: 'Loading...', - logFilter: null, - logInterval: null, }; }, computed: { From a3909774f788cdb0d673422fbeed242a85a3cfcb Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:35:07 -0400 Subject: [PATCH 40/86] Additional variable reordering --- src_assets/common/assets/web/troubleshooting.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 260c77b82f7..fe2b062ca20 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -144,10 +144,10 @@

      {{ $t('troubleshooting.logs') }}

      logs: 'Loading...', logFilter: null, logInterval: null, - unpairAllPressed: false, - unpairAllStatus: null, restartPressed: false, showApplyMessage: false, + unpairAllPressed: false, + unpairAllStatus: null, }; }, computed: { From a64bfc42c7d47b467ee27ffe64bf0415587e131a Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 18 Apr 2024 09:31:38 -0400 Subject: [PATCH 41/86] Re-use navbar.pin string --- src_assets/common/assets/web/pin.html | 2 +- src_assets/common/assets/web/public/assets/locale/en.json | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 82bbcd7c426..8375fa1268c 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -11,7 +11,7 @@

      {{ $t('pin.pin_pairing') }}

      - +
      diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 83f43b6f5f0..d05b5e9cb57 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -325,7 +325,7 @@ "configuration": "Configuration", "home": "Home", "password": "Change Password", - "pin": "Pin", + "pin": "PIN", "troubleshoot": "Troubleshooting" }, "password": { @@ -340,7 +340,6 @@ "device_name": "Device Name", "pair_failure": "Pairing Failed: Check if the PIN is typed correctly", "pair_success": "Success! Please check Moonlight to continue", - "pin": "PIN", "pin_pairing": "PIN Pairing", "send": "Send", "warning_msg": "Make sure you have access to the client you are pairing with. This software can give total control to your computer, so be careful!" From e30ccb4cdac94678dbfddc1b9e24276a5fd073b2 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:01:02 -0400 Subject: [PATCH 42/86] Update src_assets/common/assets/web/public/assets/locale/en.json Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/public/assets/locale/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index d05b5e9cb57..3c2f6d5aa1d 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -325,7 +325,7 @@ "configuration": "Configuration", "home": "Home", "password": "Change Password", - "pin": "PIN", + "pin": "Pin", "troubleshoot": "Troubleshooting" }, "password": { From f5a0916e9a2c1c33afbe047b4d894aa50eb089e9 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:01:50 -0400 Subject: [PATCH 43/86] Update src_assets/common/assets/web/troubleshooting.html Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/troubleshooting.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index fe2b062ca20..18db89807d7 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -91,7 +91,7 @@

      {{ $t('troubleshooting.unpair_title'
      {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_single_success') }}

      -
      +
      {{ $t('troubleshooting.unpair_all_success') }}
      From 52cb99611012dabdebb8caae51fb211bd8fdc58b Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:19:53 -0400 Subject: [PATCH 44/86] Rename unpair_all_desc to unpair_desc --- src_assets/common/assets/web/public/assets/locale/en.json | 2 +- src_assets/common/assets/web/troubleshooting.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 3c2f6d5aa1d..7dfde1879df 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -367,9 +367,9 @@ "restart_sunshine_success": "Sunshine is restarting", "troubleshooting": "Troubleshooting", "unpair_all": "Unpair All", - "unpair_all_desc": "Remove your paired devices. Individually unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_all_error": "Error while unpairing", "unpair_all_success": "All devices unpaired.", + "unpair_desc": "Remove your paired devices. Individually unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_single_no_devices": "There are no paired devices.", "unpair_single_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", "unpair_single_unknown": "Unknown Client", diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 18db89807d7..2c40529509b 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -86,7 +86,7 @@

      {{ $t('troubleshooting.unpair_title'


      -

      {{ $t('troubleshooting.unpair_all_desc') }}

      +

      {{ $t('troubleshooting.unpair_desc') }}

      {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_single_success') }}
      From 5a474dd156fff15723da187631caaaa6d99f847d Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 09:41:09 -0500 Subject: [PATCH 45/86] Assign name to certs when confirming PIN --- src/confighttp.cpp | 3 +- src/nvhttp.cpp | 46 ++++++++++++++++++++++++--- src/nvhttp.h | 2 +- src_assets/common/assets/web/pin.html | 7 ++-- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index de25bf0e7cf..9e8e5a5b4e8 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -693,7 +693,8 @@ namespace confighttp { // TODO: Input Validation pt::read_json(ss, inputTree); std::string pin = inputTree.get("pin"); - outputTree.put("status", nvhttp::pin(pin)); + std::string name = inputTree.get("name"); + outputTree.put("status", nvhttp::pin(pin, name)); } catch (std::exception &e) { BOOST_LOG(warning) << "SavePin: "sv << e.what(); diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 70ca9bc79be..fd86bd646f4 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -117,9 +117,15 @@ namespace nvhttp { std::string pkey; } conf_intern; + struct named_cert_t { + std::string name; + std::string cert; + }; + struct client_t { std::string uniqueID; std::vector certs; + std::vector named_certs; }; struct pair_session_t { @@ -201,7 +207,15 @@ namespace nvhttp { cert_node.put_value(cert); cert_nodes.push_back(std::make_pair(""s, cert_node)); } - node.add_child("certs"s, cert_nodes); + + pt::ptree named_cert_nodes; + for (auto &named_cert : client.named_certs) { + pt::ptree named_cert_node; + named_cert_node.put("name"s, named_cert.name); + named_cert_node.put("cert"s, named_cert.cert); + named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); + } + node.add_child("named_certs"s, named_cert_nodes); nodes.push_back(std::make_pair(""s, node)); } @@ -249,8 +263,21 @@ namespace nvhttp { client.uniqueID = uniqID; + // Import from old format for (auto &[_, el] : device_node.get_child("certs")) { - client.certs.emplace_back(el.get_value()); + named_cert_t named_cert; + named_cert.name = ""s; + named_cert.cert = el.get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); + } + + for (auto &[_, el] : device_node.get_child("named_certs")) { + named_cert_t named_cert; + named_cert.name = el.get_child("name").get_value(); + named_cert.cert = el.get_child("cert").get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); } } } @@ -579,15 +606,16 @@ namespace nvhttp { /** * @brief Compare the user supplied pin to the Moonlight pin. * @param pin The user supplied pin. + * @param name The user supplied name. * @return `true` if the pin is correct, `false` otherwise. * * EXAMPLES: * ```cpp - * bool pin_status = nvhttp::pin("1234"); + * bool pin_status = nvhttp::pin("1234", "laptop"); * ``` */ bool - pin(std::string pin) { + pin(std::string pin, std::string name) { pt::ptree tree; if (map_id_sess.empty()) { return false; @@ -613,6 +641,13 @@ namespace nvhttp { auto &sess = std::begin(map_id_sess)->second; getservercert(sess, tree, pin); + // set up named cert + auto &client = map_id_client[sess.client.uniqueID]; + named_cert_t named_cert; + named_cert.name = name; + named_cert.cert = sess.client.cert; + client.named_certs.emplace_back(named_cert); + // response to the request for pin std::ostringstream data; pt::write_xml(data, tree); @@ -1024,6 +1059,9 @@ namespace nvhttp { for (auto &cert : client.certs) { cert_chain.add(crypto::x509(cert)); } + for (auto &named_cert : client.named_certs) { + cert_chain.add(crypto::x509(named_cert.cert)); + } } auto add_cert = std::make_shared>(30); diff --git a/src/nvhttp.h b/src/nvhttp.h index 3be24b3de06..0a5862514c4 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -43,7 +43,7 @@ namespace nvhttp { void start(); bool - pin(std::string pin); + pin(std::string pin, std::string name); void erase_all_clients(); } // namespace nvhttp diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 359c5e527ba..90e0b8ee5bc 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -11,7 +11,8 @@

      {{ $t('pin.pin_pairing') }}

      - + +
      @@ -39,8 +40,9 @@

      {{ $t('pin.pin_pairing') }}

      document.querySelector("#form").addEventListener("submit", (e) => { e.preventDefault(); let pin = document.querySelector("#pin-input").value; + let name = document.querySelector("#name-input").value; document.querySelector("#status").innerHTML = ""; - let b = JSON.stringify({ pin: pin }); + let b = JSON.stringify({ pin: pin, name: name }); fetch("/api/pin", { method: "POST", body: b }) .then((response) => response.json()) .then((response) => { @@ -49,6 +51,7 @@

      {{ $t('pin.pin_pairing') }}

      "#status" ).innerHTML = ``; document.querySelector("#pin-input").value = ""; + document.querySelector("#name-input").value = ""; } else { document.querySelector( "#status" From 90975aa5409be70de4fd53f695e8bcebb1e27032 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:16:25 -0500 Subject: [PATCH 46/86] Don't prepare nodes for old format --- src/nvhttp.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index fd86bd646f4..8028d196a6f 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -201,13 +201,6 @@ namespace nvhttp { node.put("uniqueid"s, client.uniqueID); - pt::ptree cert_nodes; - for (auto &cert : client.certs) { - pt::ptree cert_node; - cert_node.put_value(cert); - cert_nodes.push_back(std::make_pair(""s, cert_node)); - } - pt::ptree named_cert_nodes; for (auto &named_cert : client.named_certs) { pt::ptree named_cert_node; From ec900bede8c7ae5663578aa9f7684af009df6904 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:17:22 -0500 Subject: [PATCH 47/86] Only read "certs" and "named_certs" if available --- src/nvhttp.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 8028d196a6f..d0c265d8f7b 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -257,20 +257,24 @@ namespace nvhttp { client.uniqueID = uniqID; // Import from old format - for (auto &[_, el] : device_node.get_child("certs")) { - named_cert_t named_cert; - named_cert.name = ""s; - named_cert.cert = el.get_value(); - client.named_certs.emplace_back(named_cert); - client.certs.emplace_back(named_cert.cert); + if(device_node.count("certs")) { + for (auto &[_, el] : device_node.get_child("certs")) { + named_cert_t named_cert; + named_cert.name = ""s; + named_cert.cert = el.get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); + } } - for (auto &[_, el] : device_node.get_child("named_certs")) { - named_cert_t named_cert; - named_cert.name = el.get_child("name").get_value(); - named_cert.cert = el.get_child("cert").get_value(); - client.named_certs.emplace_back(named_cert); - client.certs.emplace_back(named_cert.cert); + if(device_node.count("named_certs")) { + for (auto &[_, el] : device_node.get_child("named_certs")) { + named_cert_t named_cert; + named_cert.name = el.get_child("name").get_value(); + named_cert.cert = el.get_child("cert").get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); + } } } } From 2f97e4d9cd77953ab0f794d374baf6c73597ce27 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:17:55 -0500 Subject: [PATCH 48/86] Generate and track uniqueID for named certs --- src/nvhttp.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index d0c265d8f7b..a24138bf4ac 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -119,6 +119,7 @@ namespace nvhttp { struct named_cert_t { std::string name; + std::string uniqueID; std::string cert; }; @@ -206,6 +207,7 @@ namespace nvhttp { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); + named_cert_node.put("uniqueID"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } node.add_child("named_certs"s, named_cert_nodes); @@ -262,6 +264,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = ""s; named_cert.cert = el.get_value(); + named_cert.uniqueID = uuid_util::uuid_t::generate().string(); client.named_certs.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } @@ -272,6 +275,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); named_cert.cert = el.get_child("cert").get_value(); + named_cert.uniqueID = el.get_child("uniqueID").get_value(); client.named_certs.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } @@ -643,6 +647,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = name; named_cert.cert = sess.client.cert; + named_cert.uniqueID = uuid_util::uuid_t::generate().string(); client.named_certs.emplace_back(named_cert); // response to the request for pin From 46253711e2ec3a45691ea3875201f025870a33a4 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 21:57:41 -0500 Subject: [PATCH 49/86] API to list paired clients --- src/confighttp.cpp | 23 +++++++++++++++++++++++ src/nvhttp.cpp | 15 +++++++++++++++ src/nvhttp.h | 5 +++++ 3 files changed, 43 insertions(+) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 9e8e5a5b4e8..08443f77314 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -721,6 +721,28 @@ namespace confighttp { outputTree.put("status", true); } + void + listClients(resp_https_t response, req_https_t request) { + if (!authenticate(response, request)) return; + + print_req(request); + + pt::ptree named_certs = nvhttp::get_all_clients(); + + pt::ptree outputTree; + + outputTree.put("status", false); + + auto g = util::fail_guard([&]() { + std::ostringstream data; + pt::write_json(data, outputTree); + response->write(data.str()); + }); + + outputTree.add_child("named_certs", named_certs); + outputTree.put("status", true); + } + void closeApp(resp_https_t response, req_https_t request) { if (!authenticate(response, request)) return; @@ -767,6 +789,7 @@ namespace confighttp { server.resource["^/api/password$"]["POST"] = savePassword; server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; + server.resource["^/api/clients/list$"]["GET"] = listClients; server.resource["^/api/apps/close$"]["POST"] = closeApp; server.resource["^/api/covers/upload$"]["POST"] = uploadCover; server.resource["^/images/sunshine.ico$"]["GET"] = getFaviconImage; diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index a24138bf4ac..4d637db12d6 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -779,6 +779,21 @@ namespace nvhttp { response->close_connection_after_response = true; } + pt::ptree + get_all_clients() { + pt::ptree named_cert_nodes; + for (auto &[_, client] : map_id_client) { + for (auto &named_cert : client.named_certs) { + pt::ptree named_cert_node; + named_cert_node.put("name"s, named_cert.name); + named_cert_node.put("uniqueID"s, named_cert.uniqueID); + named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); + } + } + + return named_cert_nodes; + } + void applist(resp_https_t response, req_https_t request) { print_req(request); diff --git a/src/nvhttp.h b/src/nvhttp.h index 0a5862514c4..11df8fc6f56 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -9,6 +9,9 @@ // standard includes #include +// lib includes +#include + // local includes #include "thread_safe.h" @@ -44,6 +47,8 @@ namespace nvhttp { start(); bool pin(std::string pin, std::string name); + boost::property_tree::ptree + get_all_clients(); void erase_all_clients(); } // namespace nvhttp From 0ef01081e81cb7b38a3f4e56af031effd578e412 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Fri, 19 Jan 2024 21:59:35 -0500 Subject: [PATCH 50/86] API to unpair clients --- src/confighttp.cpp | 32 ++++++++++++++++++++++++++++++++ src/nvhttp.cpp | 23 +++++++++++++++++++++++ src/nvhttp.h | 2 ++ 3 files changed, 57 insertions(+) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 08443f77314..d042846c90f 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -721,6 +721,37 @@ namespace confighttp { outputTree.put("status", true); } + void + unpairClient(resp_https_t response, req_https_t request) { + if (!authenticate(response, request)) return; + + print_req(request); + + std::stringstream ss; + ss << request->content.rdbuf(); + + pt::ptree inputTree, outputTree; + + auto g = util::fail_guard([&]() { + std::ostringstream data; + pt::write_json(data, outputTree); + response->write(data.str()); + }); + + try { + // TODO: Input Validation + pt::read_json(ss, inputTree); + std::string uniqueid = inputTree.get("uniqueid"); + outputTree.put("status", nvhttp::unpair_client(uniqueid)); + } + catch (std::exception &e) { + BOOST_LOG(warning) << "UnpairClient: "sv << e.what(); + outputTree.put("status", false); + outputTree.put("error", e.what()); + return; + } + } + void listClients(resp_https_t response, req_https_t request) { if (!authenticate(response, request)) return; @@ -790,6 +821,7 @@ namespace confighttp { server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; server.resource["^/api/clients/list$"]["GET"] = listClients; + server.resource["^/api/clients/unpair-single$"]["POST"] = unpairClient; server.resource["^/api/apps/close$"]["POST"] = closeApp; server.resource["^/api/covers/upload$"]["POST"] = uploadCover; server.resource["^/images/sunshine.ico$"]["GET"] = getFaviconImage; diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 4d637db12d6..cbb60124358 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -1208,4 +1208,27 @@ namespace nvhttp { cert_chain.clear(); save_state(); } + + /** + * @brief Remove all single client. + * + * EXAMPLES: + * ```cpp + * nvhttp::unpair_client("4D7BB2DD-5704-A405-B41C-891A022932E1"); + * ``` + */ + bool + unpair_client(std::string uniqueID) { + for (auto &[_, client] : map_id_client) { + for (auto it = client.named_certs.begin(); it != client.named_certs.end();) + { + if ((*it).uniqueID == uniqueID) + it = client.named_certs.erase(it); + else + ++it; + } + } + save_state(); + return true; + } } // namespace nvhttp diff --git a/src/nvhttp.h b/src/nvhttp.h index 11df8fc6f56..f150bae14e1 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -47,6 +47,8 @@ namespace nvhttp { start(); bool pin(std::string pin, std::string name); + bool + unpair_client(std::string uniqueid); boost::property_tree::ptree get_all_clients(); void From 65dd1d7419600df3f248e07becc14652d437942c Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 02:58:15 -0500 Subject: [PATCH 51/86] During unpairing, also remove cert from client.certs --- src/nvhttp.cpp | 29 ++++++++++++++++++++++------- src/nvhttp.h | 2 +- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index cbb60124358..c8987f18adb 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -1217,18 +1217,33 @@ namespace nvhttp { * nvhttp::unpair_client("4D7BB2DD-5704-A405-B41C-891A022932E1"); * ``` */ - bool + int unpair_client(std::string uniqueID) { + int removed = 0; for (auto &[_, client] : map_id_client) { - for (auto it = client.named_certs.begin(); it != client.named_certs.end();) - { - if ((*it).uniqueID == uniqueID) + for (auto it = client.named_certs.begin(); it != client.named_certs.end();) { + if ((*it).uniqueID == uniqueID) { + // Find matching cert and remove it + for (auto cert = client.certs.begin(); cert != client.certs.end();) { + if ((*cert) == (*it).cert) { + cert = client.certs.erase(cert); + removed++; + } + else { + ++cert; + } + } + + // And then remove the named cert it = client.named_certs.erase(it); - else + removed++; + } + else { ++it; - } + } + } } save_state(); - return true; + return removed; } } // namespace nvhttp diff --git a/src/nvhttp.h b/src/nvhttp.h index f150bae14e1..6fdf202ac29 100644 --- a/src/nvhttp.h +++ b/src/nvhttp.h @@ -47,7 +47,7 @@ namespace nvhttp { start(); bool pin(std::string pin, std::string name); - bool + int unpair_client(std::string uniqueid); boost::property_tree::ptree get_all_clients(); From b00ffc7ecfc665ddd3c1b7e5513703324b12fe5b Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 02:59:37 -0500 Subject: [PATCH 52/86] Added UI for unpairing individual clients --- src_assets/common/assets/web/pin.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 90e0b8ee5bc..6dfa2a085fe 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -20,6 +20,19 @@

      {{ $t('pin.pin_pairing') }}

      +
      +
      +
      +

      Paired Clients

      +
      Refresh
      +
      +
      +
      Success! Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions.
      + +
      +
        +
        +
        From 280dd81d70b54b4425ac360094e195c7b188c771 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 04:05:45 -0500 Subject: [PATCH 53/86] Formatting --- src/nvhttp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index c8987f18adb..7e3e1fb4f8a 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -259,7 +259,7 @@ namespace nvhttp { client.uniqueID = uniqID; // Import from old format - if(device_node.count("certs")) { + if (device_node.count("certs")) { for (auto &[_, el] : device_node.get_child("certs")) { named_cert_t named_cert; named_cert.name = ""s; @@ -270,7 +270,7 @@ namespace nvhttp { } } - if(device_node.count("named_certs")) { + if (device_node.count("named_certs")) { for (auto &[_, el] : device_node.get_child("named_certs")) { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); @@ -790,7 +790,7 @@ namespace nvhttp { named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } } - + return named_cert_nodes; } From 9d84f6805c5932cfc5098a37d3665d438063809b Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 04:16:48 -0500 Subject: [PATCH 54/86] Comment typo --- src/nvhttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 7e3e1fb4f8a..160b9536583 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -1210,7 +1210,7 @@ namespace nvhttp { } /** - * @brief Remove all single client. + * @brief Remove single client. * * EXAMPLES: * ```cpp From 9812f2e92b1b8be3c4df96b25f592d2326ae2e40 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 20 Jan 2024 04:43:14 -0500 Subject: [PATCH 55/86] Use lowercase property name for consistency --- src/nvhttp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 160b9536583..0dfc02df880 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -207,7 +207,7 @@ namespace nvhttp { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); - named_cert_node.put("uniqueID"s, named_cert.uniqueID); + named_cert_node.put("uniqueid"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } node.add_child("named_certs"s, named_cert_nodes); @@ -275,7 +275,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); named_cert.cert = el.get_child("cert").get_value(); - named_cert.uniqueID = el.get_child("uniqueID").get_value(); + named_cert.uniqueID = el.get_child("uniqueid").get_value(); client.named_certs.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } From b17e3ac2081946e87c040f9a33f132cbea88578e Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:33:44 -0500 Subject: [PATCH 56/86] Update sunshine_state.json format to no longer use root.devices sunshine_state.json now follows the format outlined in https://github.com/LizardByte/Sunshine/pull/2042#issuecomment-1904634424 --- src/nvhttp.cpp | 70 +++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 0dfc02df880..a5d4fdec4a3 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -196,7 +196,6 @@ namespace nvhttp { root.erase("root"s); root.put("root.uniqueid", http::unique_id); - auto &nodes = root.add_child("root.devices", pt::ptree {}); for (auto &[_, client] : map_id_client) { pt::ptree node; @@ -207,12 +206,10 @@ namespace nvhttp { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); - named_cert_node.put("uniqueid"s, named_cert.uniqueID); + named_cert_node.put("uuid"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } - node.add_child("named_certs"s, named_cert_nodes); - - nodes.push_back(std::make_pair(""s, node)); + root.add_child("root.named_certs"s, named_cert_nodes); } try { @@ -232,9 +229,9 @@ namespace nvhttp { return; } - pt::ptree root; + pt::ptree tree; try { - pt::read_json(config::nvhttp.file_state, root); + pt::read_json(config::nvhttp.file_state, tree); } catch (std::exception &e) { BOOST_LOG(error) << "Couldn't read "sv << config::nvhttp.file_state << ": "sv << e.what(); @@ -242,7 +239,7 @@ namespace nvhttp { return; } - auto unique_id_p = root.get_optional("root.uniqueid"); + auto unique_id_p = tree.get_optional("root.uniqueid"); if (!unique_id_p) { // This file doesn't contain moonlight credentials http::unique_id = uuid_util::uuid_t::generate().string(); @@ -250,35 +247,38 @@ namespace nvhttp { } http::unique_id = std::move(*unique_id_p); - auto device_nodes = root.get_child("root.devices"); - - for (auto &[_, device_node] : device_nodes) { - auto uniqID = device_node.get("uniqueid"); - auto &client = map_id_client.emplace(uniqID, client_t {}).first->second; - - client.uniqueID = uniqID; - - // Import from old format - if (device_node.count("certs")) { - for (auto &[_, el] : device_node.get_child("certs")) { - named_cert_t named_cert; - named_cert.name = ""s; - named_cert.cert = el.get_value(); - named_cert.uniqueID = uuid_util::uuid_t::generate().string(); - client.named_certs.emplace_back(named_cert); - client.certs.emplace_back(named_cert.cert); + auto root = tree.get_child("root"); + auto &client = map_id_client.emplace("0123456789ABCDEF"s, client_t {}).first->second; + client.uniqueID = "0123456789ABCDEF"s; + + // Import from old format + if(root.get_child_optional("devices")) { + auto device_nodes = root.get_child("devices"); + for (auto &[_, device_node] : device_nodes) { + auto uniqID = device_node.get("uniqueid"); + + if (device_node.count("certs")) { + for (auto &[_, el] : device_node.get_child("certs")) { + named_cert_t named_cert; + named_cert.name = ""s; + named_cert.cert = el.get_value(); + named_cert.uniqueID = uuid_util::uuid_t::generate().string(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); + } } } - - if (device_node.count("named_certs")) { - for (auto &[_, el] : device_node.get_child("named_certs")) { - named_cert_t named_cert; - named_cert.name = el.get_child("name").get_value(); - named_cert.cert = el.get_child("cert").get_value(); - named_cert.uniqueID = el.get_child("uniqueid").get_value(); - client.named_certs.emplace_back(named_cert); - client.certs.emplace_back(named_cert.cert); - } + } + + + if (root.count("named_certs")) { + for (auto &[_, el] : root.get_child("named_certs")) { + named_cert_t named_cert; + named_cert.name = el.get_child("name").get_value(); + named_cert.cert = el.get_child("cert").get_value(); + named_cert.uniqueID = el.get_child("uuid").get_value(); + client.named_certs.emplace_back(named_cert); + client.certs.emplace_back(named_cert.cert); } } } From ff0f02b96bbc78936f8d3bda23c8d52634cc1140 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:37:47 -0500 Subject: [PATCH 57/86] Formatting --- src/nvhttp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index a5d4fdec4a3..05b9ef06d79 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -252,8 +252,8 @@ namespace nvhttp { client.uniqueID = "0123456789ABCDEF"s; // Import from old format - if(root.get_child_optional("devices")) { - auto device_nodes = root.get_child("devices"); + if (root.get_child_optional("devices")) { + auto device_nodes = root.get_child("devices"); for (auto &[_, device_node] : device_nodes) { auto uniqID = device_node.get("uniqueid"); From c2e6d0361c93643dad510ec9f009aff8b32c9831 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:46:39 -0500 Subject: [PATCH 58/86] Formatting --- src/nvhttp.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 05b9ef06d79..13364ad5487 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -268,9 +268,8 @@ namespace nvhttp { } } } - } + } - if (root.count("named_certs")) { for (auto &[_, el] : root.get_child("named_certs")) { named_cert_t named_cert; From d9b0bfa0640bcaff0a5a9f1ac0773836dde32cea Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 17:11:26 -0500 Subject: [PATCH 59/86] Refactor map_id_client into a single client_t --- src/nvhttp.cpp | 111 +++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 13364ad5487..78b5da24c02 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -152,7 +152,7 @@ namespace nvhttp { // uniqueID, session std::unordered_map map_id_sess; - std::unordered_map map_id_client; + client_t client_root; std::atomic session_id_counter; using args_t = SimpleWeb::CaseInsensitiveMultimap; @@ -196,21 +196,20 @@ namespace nvhttp { root.erase("root"s); root.put("root.uniqueid", http::unique_id); - for (auto &[_, client] : map_id_client) { - pt::ptree node; - - node.put("uniqueid"s, client.uniqueID); - - pt::ptree named_cert_nodes; - for (auto &named_cert : client.named_certs) { - pt::ptree named_cert_node; - named_cert_node.put("name"s, named_cert.name); - named_cert_node.put("cert"s, named_cert.cert); - named_cert_node.put("uuid"s, named_cert.uniqueID); - named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); - } - root.add_child("root.named_certs"s, named_cert_nodes); + client_t &client = client_root; + pt::ptree node; + + node.put("uniqueid"s, client.uniqueID); + + pt::ptree named_cert_nodes; + for (auto &named_cert : client.named_certs) { + pt::ptree named_cert_node; + named_cert_node.put("name"s, named_cert.name); + named_cert_node.put("cert"s, named_cert.cert); + named_cert_node.put("uuid"s, named_cert.uniqueID); + named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } + root.add_child("root.named_certs"s, named_cert_nodes); try { pt::write_json(config::nvhttp.file_state, root); @@ -248,7 +247,7 @@ namespace nvhttp { http::unique_id = std::move(*unique_id_p); auto root = tree.get_child("root"); - auto &client = map_id_client.emplace("0123456789ABCDEF"s, client_t {}).first->second; + client_t client; client.uniqueID = "0123456789ABCDEF"s; // Import from old format @@ -280,18 +279,21 @@ namespace nvhttp { client.certs.emplace_back(named_cert.cert); } } + client_root = client; } void update_id_client(const std::string &uniqueID, std::string &&cert, op_e op) { switch (op) { case op_e::ADD: { - auto &client = map_id_client[uniqueID]; + client_t &client = client_root; client.certs.emplace_back(std::move(cert)); client.uniqueID = uniqueID; } break; case op_e::REMOVE: - map_id_client.erase(uniqueID); + client_t client; + client.uniqueID = uniqueID; + client_root = client; break; } @@ -642,7 +644,7 @@ namespace nvhttp { getservercert(sess, tree, pin); // set up named cert - auto &client = map_id_client[sess.client.uniqueID]; + client_t &client = client_root; named_cert_t named_cert; named_cert.name = name; named_cert.cert = sess.client.cert; @@ -681,7 +683,7 @@ namespace nvhttp { auto clientID = args.find("uniqueid"s); if (clientID != std::end(args)) { - if (auto it = map_id_client.find(clientID->second); it != std::end(map_id_client)) { + if (client_root.uniqueID == clientID->second) { pair_status = 1; } } @@ -781,13 +783,12 @@ namespace nvhttp { pt::ptree get_all_clients() { pt::ptree named_cert_nodes; - for (auto &[_, client] : map_id_client) { - for (auto &named_cert : client.named_certs) { - pt::ptree named_cert_node; - named_cert_node.put("name"s, named_cert.name); - named_cert_node.put("uniqueID"s, named_cert.uniqueID); - named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); - } + client_t &client = client_root; + for (auto &named_cert : client.named_certs) { + pt::ptree named_cert_node; + named_cert_node.put("name"s, named_cert.name); + named_cert_node.put("uniqueID"s, named_cert.uniqueID); + named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } return named_cert_nodes; @@ -1071,13 +1072,12 @@ namespace nvhttp { conf_intern.pkey = file_handler::read_file(config::nvhttp.pkey.c_str()); conf_intern.servercert = file_handler::read_file(config::nvhttp.cert.c_str()); - for (auto &[_, client] : map_id_client) { - for (auto &cert : client.certs) { - cert_chain.add(crypto::x509(cert)); - } - for (auto &named_cert : client.named_certs) { - cert_chain.add(crypto::x509(named_cert.cert)); - } + client_t &client = client_root; + for (auto &cert : client.certs) { + cert_chain.add(crypto::x509(cert)); + } + for (auto &named_cert : client.named_certs) { + cert_chain.add(crypto::x509(named_cert.cert)); } auto add_cert = std::make_shared>(30); @@ -1203,8 +1203,9 @@ namespace nvhttp { */ void erase_all_clients() { - map_id_client.clear(); - cert_chain.clear(); + client_t client; + client.uniqueID = "0123456789ABCDEF"s; + client_root = client; save_state(); } @@ -1219,29 +1220,29 @@ namespace nvhttp { int unpair_client(std::string uniqueID) { int removed = 0; - for (auto &[_, client] : map_id_client) { - for (auto it = client.named_certs.begin(); it != client.named_certs.end();) { - if ((*it).uniqueID == uniqueID) { - // Find matching cert and remove it - for (auto cert = client.certs.begin(); cert != client.certs.end();) { - if ((*cert) == (*it).cert) { - cert = client.certs.erase(cert); - removed++; - } - else { - ++cert; - } + client_t &client = client_root; + for (auto it = client.named_certs.begin(); it != client.named_certs.end();) { + if ((*it).uniqueID == uniqueID) { + // Find matching cert and remove it + for (auto cert = client.certs.begin(); cert != client.certs.end();) { + if ((*cert) == (*it).cert) { + cert = client.certs.erase(cert); + removed++; + } + else { + ++cert; } - - // And then remove the named cert - it = client.named_certs.erase(it); - removed++; - } - else { - ++it; } + + // And then remove the named cert + it = client.named_certs.erase(it); + removed++; + } + else { + ++it; } } + save_state(); return removed; } From e1698bafdf430906a9ba2e4ede62447882bebade Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 24 Jan 2024 17:17:10 -0500 Subject: [PATCH 60/86] Rename named_certs to named_devices --- src/nvhttp.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 78b5da24c02..7bd0ad4d9c6 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -126,7 +126,7 @@ namespace nvhttp { struct client_t { std::string uniqueID; std::vector certs; - std::vector named_certs; + std::vector named_devices; }; struct pair_session_t { @@ -202,14 +202,14 @@ namespace nvhttp { node.put("uniqueid"s, client.uniqueID); pt::ptree named_cert_nodes; - for (auto &named_cert : client.named_certs) { + for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); named_cert_node.put("uuid"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } - root.add_child("root.named_certs"s, named_cert_nodes); + root.add_child("root.named_devices"s, named_cert_nodes); try { pt::write_json(config::nvhttp.file_state, root); @@ -262,20 +262,20 @@ namespace nvhttp { named_cert.name = ""s; named_cert.cert = el.get_value(); named_cert.uniqueID = uuid_util::uuid_t::generate().string(); - client.named_certs.emplace_back(named_cert); + client.named_devices.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } } } } - if (root.count("named_certs")) { - for (auto &[_, el] : root.get_child("named_certs")) { + if (root.count("named_devices")) { + for (auto &[_, el] : root.get_child("named_devices")) { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); named_cert.cert = el.get_child("cert").get_value(); named_cert.uniqueID = el.get_child("uuid").get_value(); - client.named_certs.emplace_back(named_cert); + client.named_devices.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } } @@ -649,7 +649,7 @@ namespace nvhttp { named_cert.name = name; named_cert.cert = sess.client.cert; named_cert.uniqueID = uuid_util::uuid_t::generate().string(); - client.named_certs.emplace_back(named_cert); + client.named_devices.emplace_back(named_cert); // response to the request for pin std::ostringstream data; @@ -784,7 +784,7 @@ namespace nvhttp { get_all_clients() { pt::ptree named_cert_nodes; client_t &client = client_root; - for (auto &named_cert : client.named_certs) { + for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("uniqueID"s, named_cert.uniqueID); @@ -1076,7 +1076,7 @@ namespace nvhttp { for (auto &cert : client.certs) { cert_chain.add(crypto::x509(cert)); } - for (auto &named_cert : client.named_certs) { + for (auto &named_cert : client.named_devices) { cert_chain.add(crypto::x509(named_cert.cert)); } @@ -1221,7 +1221,7 @@ namespace nvhttp { unpair_client(std::string uniqueID) { int removed = 0; client_t &client = client_root; - for (auto it = client.named_certs.begin(); it != client.named_certs.end();) { + for (auto it = client.named_devices.begin(); it != client.named_devices.end();) { if ((*it).uniqueID == uniqueID) { // Find matching cert and remove it for (auto cert = client.certs.begin(); cert != client.certs.end();) { @@ -1235,7 +1235,7 @@ namespace nvhttp { } // And then remove the named cert - it = client.named_certs.erase(it); + it = client.named_devices.erase(it); removed++; } else { From a1d83ecb89550de2006797927212e93f2fc9ae78 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 21:20:11 -0500 Subject: [PATCH 61/86] Update API to use uuid instead of uniqueid for clients --- src/confighttp.cpp | 4 ++-- src/nvhttp.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index d042846c90f..cc0ea938457 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -741,8 +741,8 @@ namespace confighttp { try { // TODO: Input Validation pt::read_json(ss, inputTree); - std::string uniqueid = inputTree.get("uniqueid"); - outputTree.put("status", nvhttp::unpair_client(uniqueid)); + std::string uuid = inputTree.get("uuid"); + outputTree.put("status", nvhttp::unpair_client(uuid)); } catch (std::exception &e) { BOOST_LOG(warning) << "UnpairClient: "sv << e.what(); diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 7bd0ad4d9c6..83b405956e6 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -787,7 +787,7 @@ namespace nvhttp { for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); - named_cert_node.put("uniqueID"s, named_cert.uniqueID); + named_cert_node.put("uuid"s, named_cert.uniqueID); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } From 63b3fdc1e1b7a603793d401d540f37a041d07f90 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 21:36:25 -0500 Subject: [PATCH 62/86] Move Paired Client UI to Troubleshooting page --- src_assets/common/assets/web/pin.html | 13 ---- .../common/assets/web/troubleshooting.html | 71 +++++++++++++++---- 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 6dfa2a085fe..90e0b8ee5bc 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -20,19 +20,6 @@

        {{ $t('pin.pin_pairing') }}

        -
        -
        -
        -

        Paired Clients

        -
        Refresh
        -
        -
        -
        Success! Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions.
        - -
        -
          -
          -
          diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 00497741368..098ef0abb82 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -76,23 +76,38 @@

          {{ $t('troubleshooting.restart_sunshine') }}

          -
          +
          -

          {{ $t('troubleshooting.unpair_all') }}

          -
          -

          {{ $t('troubleshooting.unpair_all_desc') }}

          -
          - {{ $t('troubleshooting.unpair_all_success') }} -
          -
          - {{ $t('troubleshooting.unpair_all_error') }} -
          -
          - +
          +
          +

          Unpair Clients

          + +
          +
          +
          Success! Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions.
          + +
          +
          + {{ $t('troubleshooting.unpair_all_success') }} +
          +
          + {{ $t('troubleshooting.unpair_all_error') }} +
          +
          +

          Remove your paired devices.

          +
            +
            +
            {{client.name != "" ? client.name : "Unknown Client"}}
            +
            +
          +
            +
            There are no paired clients.
            +
          +
          @@ -128,6 +143,8 @@

          {{ $t('troubleshooting.logs') }}

          unpairAllPressed: false, unpairAllStatus: null, restartPressed: false, + showApplyMessage: false, + clients: [], logs: 'Loading...', logFilter: null, logInterval: null, @@ -146,6 +163,7 @@

          {{ $t('troubleshooting.logs') }}

          this.refreshLogs(); }, 5000); this.refreshLogs(); + this.refreshClients(); }, beforeDestroy() { clearInterval(this.logInterval); @@ -175,6 +193,7 @@

          {{ $t('troubleshooting.logs') }}

          fetch("/api/clients/unpair", { method: "POST" }) .then((r) => r.json()) .then((r) => { + this.showApplyMessage = true; this.unpairAllPressed = false; this.unpairAllStatus = r.status.toString() === "true"; setTimeout(() => { @@ -182,6 +201,30 @@

          {{ $t('troubleshooting.logs') }}

          }, 5000); }); }, + unpairSingle(uuid) { + fetch("/api/clients/unpair-single", { method: "POST", body: JSON.stringify({ uuid }) }).then(() => { + this.showApplyMessage = true; + this.refreshClients(); + }); + }, + refreshClients() { + fetch("/api/clients/list") + .then((response) => response.json()) + .then((response) => { + const clientList = document.querySelector("#client-list"); + if (response.status === 'true' && response.named_certs && response.named_certs.length) { + this.clients = response.named_certs; + } else { + this.clients = []; + } + }); + }, + clickedApplyBanner() { + this.showApplyMessage = false; + fetch("/api/restart", { + method: "POST", + }); + }, copyLogs() { navigator.clipboard.writeText(this.actualLogs); }, From 23574bd112f03e215551eadfbb191499d567334a Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:18:51 -0500 Subject: [PATCH 63/86] Update src_assets/common/assets/web/troubleshooting.html Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/troubleshooting.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 098ef0abb82..1607c2ad4ed 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -80,7 +80,7 @@

          {{ $t('troubleshooting.restart_sunshine') }}

          -

          Unpair Clients

          +

          Unpair Clients

          From 2dfc14268c2642879b45dd3dd62a4198f0ce1c9e Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:03 -0500 Subject: [PATCH 64/86] Update src/confighttp.cpp Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src/confighttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index cc0ea938457..fcd742968bd 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -821,7 +821,7 @@ namespace confighttp { server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; server.resource["^/api/clients/list$"]["GET"] = listClients; - server.resource["^/api/clients/unpair-single$"]["POST"] = unpairClient; + server.resource["^/api/clients/unpair$"]["POST"] = unpair; server.resource["^/api/apps/close$"]["POST"] = closeApp; server.resource["^/api/covers/upload$"]["POST"] = uploadCover; server.resource["^/images/sunshine.ico$"]["GET"] = getFaviconImage; From 4a6100332e8e6ae4b9759862c0fa9ab8155e1dcd Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:25 -0500 Subject: [PATCH 65/86] Update src/confighttp.cpp Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src/confighttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index fcd742968bd..aec98a932c7 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -722,7 +722,7 @@ namespace confighttp { } void - unpairClient(resp_https_t response, req_https_t request) { + unpair(resp_https_t response, req_https_t request) { if (!authenticate(response, request)) return; print_req(request); From 1d741e6e861faa3bfde9e6b43ad13daa52213381 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:36 -0500 Subject: [PATCH 66/86] Update src/confighttp.cpp Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src/confighttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index aec98a932c7..9b2212396e7 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -745,7 +745,7 @@ namespace confighttp { outputTree.put("status", nvhttp::unpair_client(uuid)); } catch (std::exception &e) { - BOOST_LOG(warning) << "UnpairClient: "sv << e.what(); + BOOST_LOG(warning) << "Unpair: "sv << e.what(); outputTree.put("status", false); outputTree.put("error", e.what()); return; From da51e325e8490bf7f013a44bd64e69a4aa9bcc8c Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:46 -0500 Subject: [PATCH 67/86] Update src/confighttp.cpp Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src/confighttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 9b2212396e7..4ef0af75f6f 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -819,7 +819,7 @@ namespace confighttp { server.resource["^/api/restart$"]["POST"] = restart; server.resource["^/api/password$"]["POST"] = savePassword; server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; - server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; + server.resource["^/api/clients/unpair-all$"]["POST"] = unpairAll; server.resource["^/api/clients/list$"]["GET"] = listClients; server.resource["^/api/clients/unpair$"]["POST"] = unpair; server.resource["^/api/apps/close$"]["POST"] = closeApp; From 77828b29b8a9894dab93db721b97b718d03a1d56 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:41:59 -0500 Subject: [PATCH 68/86] Update src_assets/common/assets/web/troubleshooting.html Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/troubleshooting.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 1607c2ad4ed..4da3a36fd03 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -190,7 +190,7 @@

          {{ $t('troubleshooting.logs') }}

          }, unpairAll() { this.unpairAllPressed = true; - fetch("/api/clients/unpair", { method: "POST" }) + fetch("/api/clients/unpair-all", { method: "POST" }) .then((r) => r.json()) .then((r) => { this.showApplyMessage = true; From 621adf4f0917024e46eeae2de5debf6bd8aef2c3 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 25 Jan 2024 23:42:18 -0500 Subject: [PATCH 69/86] Update src_assets/common/assets/web/troubleshooting.html Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/troubleshooting.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 4da3a36fd03..4f16aebb64f 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -202,7 +202,7 @@

          {{ $t('troubleshooting.logs') }}

          }); }, unpairSingle(uuid) { - fetch("/api/clients/unpair-single", { method: "POST", body: JSON.stringify({ uuid }) }).then(() => { + fetch("/api/clients/unpair", { method: "POST", body: JSON.stringify({ uuid }) }).then(() => { this.showApplyMessage = true; this.refreshClients(); }); From 7087c9886af83b0817e2e65cfe86463472c12b7b Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sun, 28 Jan 2024 11:10:17 -0500 Subject: [PATCH 70/86] Rename device name field and mark fields as required https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-1845012932 --- src_assets/common/assets/web/pin.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 90e0b8ee5bc..a6ac0cffa06 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -11,8 +11,8 @@

          {{ $t('pin.pin_pairing') }}

          - - + +
          From bba287e433b4e1975fce5584df255f26f9c27106 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 10 Feb 2024 17:53:05 -0500 Subject: [PATCH 71/86] Remove uniqueID from client_t --- src/nvhttp.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 83b405956e6..ba21b50209b 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -124,7 +124,6 @@ namespace nvhttp { }; struct client_t { - std::string uniqueID; std::vector certs; std::vector named_devices; }; @@ -199,8 +198,6 @@ namespace nvhttp { client_t &client = client_root; pt::ptree node; - node.put("uniqueid"s, client.uniqueID); - pt::ptree named_cert_nodes; for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; @@ -248,7 +245,6 @@ namespace nvhttp { auto root = tree.get_child("root"); client_t client; - client.uniqueID = "0123456789ABCDEF"s; // Import from old format if (root.get_child_optional("devices")) { @@ -288,11 +284,9 @@ namespace nvhttp { case op_e::ADD: { client_t &client = client_root; client.certs.emplace_back(std::move(cert)); - client.uniqueID = uniqueID; } break; case op_e::REMOVE: client_t client; - client.uniqueID = uniqueID; client_root = client; break; } @@ -683,9 +677,7 @@ namespace nvhttp { auto clientID = args.find("uniqueid"s); if (clientID != std::end(args)) { - if (client_root.uniqueID == clientID->second) { - pair_status = 1; - } + pair_status = 1; } } @@ -1204,7 +1196,6 @@ namespace nvhttp { void erase_all_clients() { client_t client; - client.uniqueID = "0123456789ABCDEF"s; client_root = client; save_state(); } From 3f6072380490e3f5d3924409199e2bfad9dd7576 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Sat, 10 Feb 2024 18:09:49 -0500 Subject: [PATCH 72/86] Update named_cert_t to better match sunshine_state.json --- src/nvhttp.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index ba21b50209b..4470240bc35 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -119,7 +119,7 @@ namespace nvhttp { struct named_cert_t { std::string name; - std::string uniqueID; + std::string uuid; std::string cert; }; @@ -203,7 +203,7 @@ namespace nvhttp { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); named_cert_node.put("cert"s, named_cert.cert); - named_cert_node.put("uuid"s, named_cert.uniqueID); + named_cert_node.put("uuid"s, named_cert.uuid); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } root.add_child("root.named_devices"s, named_cert_nodes); @@ -257,7 +257,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = ""s; named_cert.cert = el.get_value(); - named_cert.uniqueID = uuid_util::uuid_t::generate().string(); + named_cert.uuid = uuid_util::uuid_t::generate().string(); client.named_devices.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } @@ -270,7 +270,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = el.get_child("name").get_value(); named_cert.cert = el.get_child("cert").get_value(); - named_cert.uniqueID = el.get_child("uuid").get_value(); + named_cert.uuid = el.get_child("uuid").get_value(); client.named_devices.emplace_back(named_cert); client.certs.emplace_back(named_cert.cert); } @@ -642,7 +642,7 @@ namespace nvhttp { named_cert_t named_cert; named_cert.name = name; named_cert.cert = sess.client.cert; - named_cert.uniqueID = uuid_util::uuid_t::generate().string(); + named_cert.uuid = uuid_util::uuid_t::generate().string(); client.named_devices.emplace_back(named_cert); // response to the request for pin @@ -779,7 +779,7 @@ namespace nvhttp { for (auto &named_cert : client.named_devices) { pt::ptree named_cert_node; named_cert_node.put("name"s, named_cert.name); - named_cert_node.put("uuid"s, named_cert.uniqueID); + named_cert_node.put("uuid"s, named_cert.uuid); named_cert_nodes.push_back(std::make_pair(""s, named_cert_node)); } @@ -1209,11 +1209,11 @@ namespace nvhttp { * ``` */ int - unpair_client(std::string uniqueID) { + unpair_client(std::string uuid) { int removed = 0; client_t &client = client_root; for (auto it = client.named_devices.begin(); it != client.named_devices.end();) { - if ((*it).uniqueID == uniqueID) { + if ((*it).uuid == uuid) { // Find matching cert and remove it for (auto cert = client.certs.begin(); cert != client.certs.end();) { if ((*cert) == (*it).cert) { From b9418eb981227acade9f223b199985e85b7f660e Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:41:14 -0400 Subject: [PATCH 73/86] Update web UI to use localization for single device pairing/unpairing --- src_assets/common/assets/web/pin.html | 6 ++--- .../assets/web/public/assets/locale/en.json | 11 ++++++--- .../common/assets/web/troubleshooting.html | 23 ++++++++----------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index a6ac0cffa06..c9501185deb 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -8,11 +8,11 @@
          -

          {{ $t('pin.pin_pairing') }}

          +

          {{ $t('pin.pin_pairing') }}

          - - + +
          diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index f0e875e1a37..5e164180dd9 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -6,6 +6,7 @@ "cancel": "Cancel", "disabled": "Disabled", "disabled_def": "Disabled (default)", + "dismiss": "Dismiss", "do_cmd": "Do Command", "elevated": "Elevated", "enabled": "Enabled", @@ -345,6 +346,7 @@ "success_msg": "Password has been changed successfully! This page will reload soon, your browser will ask you for the new credentials." }, "pin": { + "device_name": "Device Name", "pair_failure": "Pairing Failed: Check if the PIN is typed correctly", "pair_success": "Success! Please check Moonlight to continue", "pin_pairing": "PIN Pairing", @@ -373,10 +375,13 @@ "restart_sunshine_desc": "If Sunshine isn't working properly, you can try restarting it. This will terminate any running sessions.", "restart_sunshine_success": "Sunshine is restarting", "troubleshooting": "Troubleshooting", - "unpair_all": "Unpair All", - "unpair_all_desc": "Remove all your paired devices", + "unpair_all": "Unpair Devices", + "unpair_all_desc": "Remove your paired devices. Unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_all_error": "Error while unpairing", - "unpair_all_success": "Unpair Successful!" + "unpair_all_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", + "unpair_single_no_devices": "There are no paired devices.", + "unpair_single_unknown": "Unknown Client", + "unpair_title": "Unpair Devices" }, "welcome": { "confirm_password": "Confirm password", diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 4f16aebb64f..703a7c48b79 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -75,37 +75,34 @@

          {{ $t('troubleshooting.restart_sunshine') }}

          - +
          -

          Unpair Clients

          +

          {{ $t('troubleshooting.unpair_title') }}

          +
          +

          {{ $t('troubleshooting.unpair_all_desc') }}

          -
          Success! Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions.
          - -
          -
          - {{ $t('troubleshooting.unpair_all_success') }} +
          {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_all_success') }}
          +
          {{ $t('troubleshooting.unpair_all_error') }}
          -
          -

          Remove your paired devices.

            -
            {{client.name != "" ? client.name : "Unknown Client"}}
            +
            {{client.name != "" ? client.name : $t('troubleshooting.unpair_single_unknown')}}
            -
            There are no paired clients.
            +
            {{ $t('troubleshooting.unpair_single_no_devices') }}
          @@ -199,6 +196,7 @@

          {{ $t('troubleshooting.logs') }}

          setTimeout(() => { this.unpairAllStatus = null; }, 5000); + this.refreshClients(); }); }, unpairSingle(uuid) { @@ -221,9 +219,6 @@

          {{ $t('troubleshooting.logs') }}

          }, clickedApplyBanner() { this.showApplyMessage = false; - fetch("/api/restart", { - method: "POST", - }); }, copyLogs() { navigator.clipboard.writeText(this.actualLogs); From f8bfd1e38bf3ef6923c3659720ca766c6c27d204 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:42:45 -0400 Subject: [PATCH 74/86] Refresh client certs after unpairing a single client --- src/nvhttp.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 4470240bc35..ed135ffb06d 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -275,6 +275,17 @@ namespace nvhttp { client.certs.emplace_back(named_cert.cert); } } + + + // Empty certificate chain and import certs from file + cert_chain.clear(); + for (auto &cert : client.certs) { + cert_chain.add(crypto::x509(cert)); + } + for (auto &named_cert : client.named_devices) { + cert_chain.add(crypto::x509(named_cert.cert)); + } + client_root = client; } @@ -1064,14 +1075,6 @@ namespace nvhttp { conf_intern.pkey = file_handler::read_file(config::nvhttp.pkey.c_str()); conf_intern.servercert = file_handler::read_file(config::nvhttp.cert.c_str()); - client_t &client = client_root; - for (auto &cert : client.certs) { - cert_chain.add(crypto::x509(cert)); - } - for (auto &named_cert : client.named_devices) { - cert_chain.add(crypto::x509(named_cert.cert)); - } - auto add_cert = std::make_shared>(30); // resume doesn't always get the parameter "localAudioPlayMode" @@ -1235,6 +1238,7 @@ namespace nvhttp { } save_state(); + load_state(); return removed; } } // namespace nvhttp From 923ec6b934cabf90e70080d3c2431ee4e390ea9e Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:45:22 -0400 Subject: [PATCH 75/86] Rename unpair all button --- src_assets/common/assets/web/public/assets/locale/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 5e164180dd9..5419802556d 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -375,7 +375,7 @@ "restart_sunshine_desc": "If Sunshine isn't working properly, you can try restarting it. This will terminate any running sessions.", "restart_sunshine_success": "Sunshine is restarting", "troubleshooting": "Troubleshooting", - "unpair_all": "Unpair Devices", + "unpair_all": "Unpair All", "unpair_all_desc": "Remove your paired devices. Unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_all_error": "Error while unpairing", "unpair_all_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", From 02176bdcdb8fabdc6d236bf1cb04c3acba7b44d7 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 13:04:20 -0400 Subject: [PATCH 76/86] Formatting --- src/nvhttp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index ed135ffb06d..32737184202 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -275,7 +275,6 @@ namespace nvhttp { client.certs.emplace_back(named_cert.cert); } } - // Empty certificate chain and import certs from file cert_chain.clear(); From acc0890d102f4e221a0c63e6e0272cc59f7524d3 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:13:02 -0400 Subject: [PATCH 77/86] Close session when unpairing all clients https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-2007534088 --- src/confighttp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 4ef0af75f6f..a237c1fc3a7 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -718,6 +718,7 @@ namespace confighttp { response->write(data.str()); }); nvhttp::erase_all_clients(); + proc::proc.terminate(); outputTree.put("status", true); } From f7565070102fe6e9462afc291b192f4f428d9867 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:14:05 -0400 Subject: [PATCH 78/86] Localize "PIN" input placeholder https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-2007515774 --- src_assets/common/assets/web/pin.html | 2 +- src_assets/common/assets/web/public/assets/locale/en.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index c9501185deb..0c9f357daac 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -11,7 +11,7 @@

          {{ $t('pin.pin_pairing') }}

          - +
          diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 5419802556d..acb1ba82ef5 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -349,6 +349,7 @@ "device_name": "Device Name", "pair_failure": "Pairing Failed: Check if the PIN is typed correctly", "pair_success": "Success! Please check Moonlight to continue", + "pin": "PIN", "pin_pairing": "PIN Pairing", "send": "Send", "warning_msg": "Make sure you have access to the client you are pairing with. This software can give total control to your computer, so be careful!" From 37a9c8be74d7a06b529945007c6ae7bea8f28da1 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:21:35 -0400 Subject: [PATCH 79/86] Sort client list alphabetically https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-2007515774 --- src_assets/common/assets/web/troubleshooting.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 703a7c48b79..eb6de5df45d 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -211,7 +211,9 @@

          {{ $t('troubleshooting.logs') }}

          .then((response) => { const clientList = document.querySelector("#client-list"); if (response.status === 'true' && response.named_certs && response.named_certs.length) { - this.clients = response.named_certs; + this.clients = response.named_certs.sort((a, b) => { + return (a.name.toLowerCase() > b.name.toLowerCase() || a.name == "" ? 1 : -1) + }); } else { this.clients = []; } From 218d5ececf3d58dce0b35a04823237b51d99f99b Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:29:34 -0400 Subject: [PATCH 80/86] Specify that only individual unpair requires force close --- src_assets/common/assets/web/public/assets/locale/en.json | 5 +++-- src_assets/common/assets/web/troubleshooting.html | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index acb1ba82ef5..c080c30c6f2 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -377,10 +377,11 @@ "restart_sunshine_success": "Sunshine is restarting", "troubleshooting": "Troubleshooting", "unpair_all": "Unpair All", - "unpair_all_desc": "Remove your paired devices. Unpaired devices with an active session will remain connected, but cannot start or resume a session.", + "unpair_all_desc": "Remove your paired devices. Individually unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_all_error": "Error while unpairing", - "unpair_all_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", + "unpair_all_success": "All devices unpaired.", "unpair_single_no_devices": "There are no paired devices.", + "unpair_single_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", "unpair_single_unknown": "Unknown Client", "unpair_title": "Unpair Devices" }, diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index eb6de5df45d..5c38d970b05 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -88,10 +88,13 @@

          {{ $t('troubleshooting.unpair_title'

          {{ $t('troubleshooting.unpair_all_desc') }}

          -
          {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_all_success') }}
          +
          {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_single_success') }}
          -
          +
          + {{ $t('troubleshooting.unpair_all_success') }} +
          +
          {{ $t('troubleshooting.unpair_all_error') }}
          @@ -190,7 +193,6 @@

          {{ $t('troubleshooting.logs') }}

          fetch("/api/clients/unpair-all", { method: "POST" }) .then((r) => r.json()) .then((r) => { - this.showApplyMessage = true; this.unpairAllPressed = false; this.unpairAllStatus = r.status.toString() === "true"; setTimeout(() => { From 4374ab137a1011ea2bd782594f0c3abf20da1a6a Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:32:27 -0400 Subject: [PATCH 81/86] Reordered Vue page vars https://github.com/LizardByte/Sunshine/pull/2042#pullrequestreview-2007515774 --- src_assets/common/assets/web/troubleshooting.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 5c38d970b05..efa19f0b8e7 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -138,16 +138,16 @@

          {{ $t('troubleshooting.logs') }}

          }, data() { return { + clients: [], closeAppPressed: false, closeAppStatus: null, + logs: 'Loading...', + logFilter: null, + logInterval: null, unpairAllPressed: false, unpairAllStatus: null, restartPressed: false, showApplyMessage: false, - clients: [], - logs: 'Loading...', - logFilter: null, - logInterval: null, }; }, computed: { From 0f4c658c20c932341b51934ae000f6647bec3373 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:35:07 -0400 Subject: [PATCH 82/86] Additional variable reordering --- src_assets/common/assets/web/troubleshooting.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index efa19f0b8e7..b9187c2a50c 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -144,10 +144,10 @@

          {{ $t('troubleshooting.logs') }}

          logs: 'Loading...', logFilter: null, logInterval: null, - unpairAllPressed: false, - unpairAllStatus: null, restartPressed: false, showApplyMessage: false, + unpairAllPressed: false, + unpairAllStatus: null, }; }, computed: { From f376a77d8010cbc7a267da4651640da43fd659ba Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 18 Apr 2024 09:31:38 -0400 Subject: [PATCH 83/86] Re-use navbar.pin string --- src_assets/common/assets/web/pin.html | 2 +- src_assets/common/assets/web/public/assets/locale/en.json | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 0c9f357daac..7bb54662a07 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -11,7 +11,7 @@

          {{ $t('pin.pin_pairing') }}

          - +
          diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index c080c30c6f2..ff6a44bab79 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -334,7 +334,7 @@ "configuration": "Configuration", "home": "Home", "password": "Change Password", - "pin": "Pin", + "pin": "PIN", "troubleshoot": "Troubleshooting" }, "password": { @@ -349,7 +349,6 @@ "device_name": "Device Name", "pair_failure": "Pairing Failed: Check if the PIN is typed correctly", "pair_success": "Success! Please check Moonlight to continue", - "pin": "PIN", "pin_pairing": "PIN Pairing", "send": "Send", "warning_msg": "Make sure you have access to the client you are pairing with. This software can give total control to your computer, so be careful!" From 0c015c926ecbe33eb2eea14b8b38c2c0cebc99f2 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:01:02 -0400 Subject: [PATCH 84/86] Update src_assets/common/assets/web/public/assets/locale/en.json Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/public/assets/locale/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index ff6a44bab79..9ae8d70194b 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -334,7 +334,7 @@ "configuration": "Configuration", "home": "Home", "password": "Change Password", - "pin": "PIN", + "pin": "Pin", "troubleshoot": "Troubleshooting" }, "password": { From 1acd3024e7b8cee2efc1ba7e2c8f643aab157ab0 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:01:50 -0400 Subject: [PATCH 85/86] Update src_assets/common/assets/web/troubleshooting.html Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- src_assets/common/assets/web/troubleshooting.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index b9187c2a50c..a9e631cc6d6 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -91,7 +91,7 @@

          {{ $t('troubleshooting.unpair_title'
          {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_single_success') }}

          -
          +
          {{ $t('troubleshooting.unpair_all_success') }}
          From b7e8bc7b98e45464b43c17a8bc5cab94ec904378 Mon Sep 17 00:00:00 2001 From: Xander Frangos <33106561+xanderfrangos@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:19:53 -0400 Subject: [PATCH 86/86] Rename unpair_all_desc to unpair_desc --- src_assets/common/assets/web/public/assets/locale/en.json | 2 +- src_assets/common/assets/web/troubleshooting.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 9ae8d70194b..e6c62ed14b2 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -376,9 +376,9 @@ "restart_sunshine_success": "Sunshine is restarting", "troubleshooting": "Troubleshooting", "unpair_all": "Unpair All", - "unpair_all_desc": "Remove your paired devices. Individually unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_all_error": "Error while unpairing", "unpair_all_success": "All devices unpaired.", + "unpair_desc": "Remove your paired devices. Individually unpaired devices with an active session will remain connected, but cannot start or resume a session.", "unpair_single_no_devices": "There are no paired devices.", "unpair_single_success": "However, the device(s) may still be in an active session. Use the 'Force Close' button above to end any open sessions.", "unpair_single_unknown": "Unknown Client", diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index a9e631cc6d6..d54da30b0e8 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -86,7 +86,7 @@

          {{ $t('troubleshooting.unpair_title'


          -

          {{ $t('troubleshooting.unpair_all_desc') }}

          +

          {{ $t('troubleshooting.unpair_desc') }}

          {{ $t('_common.success') }} {{ $t('troubleshooting.unpair_single_success') }}