diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index e260141a7d7..a33ac63225c 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -176,6 +176,7 @@ namespace nvhttp { // Set by TLS verify callback, read by launch/resume handler (single-threaded HTTPS server) std::string last_verified_client_cert; ///< Last client certificate accepted by the TLS verify callback. // NOSONAR(cpp:S5421): intentionally mutable global + std::string last_verified_client_name; ///< Friendly name of last client certificate accepted by the TLS verify callback. // NOSONAR(cpp:S5421): intentionally mutable global /** * @brief Case-insensitive map used for HTTP headers and query parameters. @@ -405,6 +406,7 @@ namespace nvhttp { } launch_session->rtsp_url_scheme = launch_session->rtsp_cipher ? "rtspenc://"s : "rtsp://"s; launch_session->client_cert = last_verified_client_cert; + launch_session->client_name = last_verified_client_name; // Generate the unique identifiers for this connection that we will send later during RTSP handshake unsigned char raw_payload[8]; @@ -1253,12 +1255,13 @@ namespace nvhttp { } /** - * @brief Check whether a paired client certificate is allowed to connect. + * @brief Check whether a paired client certificate is allowed to connect and retrieve its friendly name. * * @param cert_pem PEM-encoded client certificate to look up. - * @return True when the client certificate belongs to an enabled device. + * @return Pair of (bool enabled, string name) where "enabled" is True when the client certificate belongs to an + enabled device and "name" is the friendly client name set during pairing. */ - bool is_client_enabled(const std::string_view cert_pem); + std::pair get_client_status(const std::string_view cert_pem); void start() { platf::set_thread_name("nvhttp"); @@ -1330,12 +1333,14 @@ namespace nvhttp { // Check if this client is enabled auto pem = crypto::pem(x509); - if (!is_client_enabled(pem)) { + auto [enabled, client_name] = get_client_status(pem); + if (!enabled) { BOOST_LOG(info) << "Client is disabled -- denied"sv; return verified; } last_verified_client_cert = pem; + last_verified_client_name = client_name; verified = 1; return verified; @@ -1463,15 +1468,15 @@ namespace nvhttp { } /** - * @brief Check whether a paired client certificate is allowed to connect. + * @brief Check whether a paired client certificate is allowed to connect and return its friendly name. */ - bool is_client_enabled(const std::string_view cert_pem) { + std::pair get_client_status(const std::string_view cert_pem) { const client_t &client = client_root; for (const auto &named_cert : client.named_devices) { if (named_cert.cert == cert_pem) { - return named_cert.enabled; + return {named_cert.enabled, named_cert.name}; } } - return true; + return {true, {}}; } } // namespace nvhttp diff --git a/src/process.cpp b/src/process.cpp index ca4b50d5552..71708825ac6 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -169,6 +169,7 @@ namespace proc { // Add Stream-specific environment variables _env["SUNSHINE_APP_ID"] = std::to_string(_app_id); _env["SUNSHINE_APP_NAME"] = _app.name; + _env["SUNSHINE_CLIENT_NAME"] = launch_session->client_name; _env["SUNSHINE_CLIENT_WIDTH"] = std::to_string(launch_session->width); _env["SUNSHINE_CLIENT_HEIGHT"] = std::to_string(launch_session->height); _env["SUNSHINE_CLIENT_FPS"] = std::to_string(launch_session->fps); diff --git a/src/rtsp.h b/src/rtsp.h index 7857835f013..8fa8dd6f5d8 100644 --- a/src/rtsp.h +++ b/src/rtsp.h @@ -38,6 +38,7 @@ namespace rtsp_stream { bool continuous_audio; ///< Whether audio packets continue during silence. bool enable_hdr; ///< Whether HDR streaming is requested. bool enable_sops; ///< Whether sequence output protection is requested. + std::string client_name; ///< Friendly client name from initial pairing. std::optional rtsp_cipher; ///< AES-GCM cipher used once encrypted RTSP is negotiated. std::string rtsp_url_scheme; ///< URL scheme selected by the RTSP SETUP flow. diff --git a/src_assets/common/assets/web/apps.html b/src_assets/common/assets/web/apps.html index 32b3e0af9ed..2fe57f41541 100644 --- a/src_assets/common/assets/web/apps.html +++ b/src_assets/common/assets/web/apps.html @@ -337,6 +337,10 @@

{{ $t('apps.env_vars_about') }}

SUNSHINE_APP_NAME {{ $t('apps.env_app_name') }} + + SUNSHINE_CLIENT_NAME + {{ $t('apps.env_client_name') }} + SUNSHINE_CLIENT_WIDTH {{ $t('apps.env_client_width') }} 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 1c0b949c6cc..2da2a139b24 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -71,6 +71,7 @@ "env_client_hdr": "HDR is enabled by the client (true/false)", "env_client_height": "The Height requested by the client (int)", "env_client_host_audio": "The client has requested host audio (true/false)", + "env_client_name": "The Name of the client assigned during pairing (str)", "env_client_width": "The Width requested by the client (int)", "env_displayplacer_example": "Example - displayplacer for Resolution Automation:", "env_qres_example": "Example - QRes for Resolution Automation:",