Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/confighttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,10 @@ namespace confighttp {
output_tree["status"] = nvhttp::set_client_enabled(uuid, enabled);

if (!enabled && output_tree["status"]) {
rtsp_stream::terminate_sessions();
auto cert = nvhttp::get_cert_by_uuid(uuid);
if (!cert.empty()) {
rtsp_stream::terminate_sessions_by_cert(cert);
}

if (rtsp_stream::session_count() == 0 && proc::proc.running() > 0) {
proc::proc.terminate();
Expand Down
14 changes: 14 additions & 0 deletions src/nvhttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ namespace nvhttp {
client_t client_root;
std::atomic<uint32_t> session_id_counter;

// Set by TLS verify callback, read by launch/resume handler (single-threaded HTTPS server)
std::string last_verified_client_cert; // NOSONAR(cpp:S5421) - intentionally mutable global

using args_t = SimpleWeb::CaseInsensitiveMultimap;
using resp_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SunshineHTTPS>::Response>;
using req_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SunshineHTTPS>::Request>;
Expand Down Expand Up @@ -326,6 +329,7 @@ namespace nvhttp {
launch_session->rtsp_iv_counter = 0;
}
launch_session->rtsp_url_scheme = launch_session->rtsp_cipher ? "rtspenc://"s : "rtsp://"s;
launch_session->client_cert = last_verified_client_cert;

// Generate the unique identifiers for this connection that we will send later during RTSP handshake
unsigned char raw_payload[8];
Expand Down Expand Up @@ -1141,6 +1145,7 @@ namespace nvhttp {
return verified;
}

last_verified_client_cert = pem;
verified = 1;

return verified;
Expand Down Expand Up @@ -1255,6 +1260,15 @@ namespace nvhttp {
return false;
}

std::string get_cert_by_uuid(const std::string_view uuid) {
for (const auto &named_cert : client_root.named_devices) {
if (named_cert.uuid == uuid) {
return named_cert.cert;
}
}
return {};
}

bool is_client_enabled(const std::string_view cert_pem) {
const client_t &client = client_root;
for (const auto &named_cert : client.named_devices) {
Expand Down
1 change: 1 addition & 0 deletions src/nvhttp.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ namespace nvhttp {
* @return true if the client was found and updated.
*/
bool set_client_enabled(std::string_view uuid, bool enabled);
std::string get_cert_by_uuid(std::string_view uuid);

/**
* @brief Get all paired clients.
Expand Down
18 changes: 18 additions & 0 deletions src/rtsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,20 @@
}
}

void clear_by_cert(std::string_view cert) {
auto lg = _session_slots.lock();

Check warning on line 573 in src/rtsp.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "std::lock_guard" with "std::scoped_lock"

See more on https://sonarcloud.io/project/issues?id=LizardByte_Sunshine&issues=AZ42R3IcHyptNfSkHXli&open=AZ42R3IcHyptNfSkHXli&pullRequest=5138
for (auto i = _session_slots->begin(); i != _session_slots->end();) {
auto &slot = *(*i);
if (stream::session::client_cert(slot) == cert) {
stream::session::stop(slot);
stream::session::join(slot);
i = _session_slots->erase(i);
} else {
i++;
}
}

Check warning on line 583 in src/rtsp.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this loop with a "std::erase_if" call.

See more on https://sonarcloud.io/project/issues?id=LizardByte_Sunshine&issues=AZ42R3IcHyptNfSkHXlh&open=AZ42R3IcHyptNfSkHXlh&pullRequest=5138
}

/**
* @brief Removes the provided session from the set of sessions.
* @param session The session to remove.
Expand Down Expand Up @@ -643,6 +657,10 @@
server.clear(true);
}

void terminate_sessions_by_cert(std::string_view cert) {
server.clear_by_cert(cert);
}

int send(tcp::socket &sock, const std::string_view &sv) {
std::size_t bytes_send = 0;

Expand Down
2 changes: 2 additions & 0 deletions src/rtsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace rtsp_stream {
constexpr auto RTSP_SETUP_PORT = 21;

struct launch_session_t {

Check warning on line 17 in src/rtsp.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this structure so it has no more than 20 fields, rather than the 21 it currently has.

See more on https://sonarcloud.io/project/issues?id=LizardByte_Sunshine&issues=AZ42R3GSHyptNfSkHXlf&open=AZ42R3GSHyptNfSkHXlf&pullRequest=5138
uint32_t id;

crypto::aes_t gcm_key;
Expand All @@ -39,6 +39,7 @@
std::optional<crypto::cipher::gcm_t> rtsp_cipher;
std::string rtsp_url_scheme;
uint32_t rtsp_iv_counter;
std::string client_cert;
};

void launch_session_raise(std::shared_ptr<launch_session_t> launch_session);
Expand All @@ -59,6 +60,7 @@
* @brief Terminates all running streaming sessions.
*/
void terminate_sessions();
void terminate_sessions_by_cert(std::string_view cert);

/**
* @brief Runs the RTSP server loop.
Expand Down
6 changes: 6 additions & 0 deletions src/stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ namespace stream {
} control;

std::uint32_t launch_session_id;
std::string client_cert;

safe::mail_raw_t::event_t<bool> shutdown_event;
safe::signal_t controlEnd;
Expand Down Expand Up @@ -1902,6 +1903,10 @@ namespace stream {
return session.state.load(std::memory_order_relaxed);
}

const std::string &client_cert(session_t &session) {
return session.client_cert;
}

void stop(session_t &session) {
while_starting_do_nothing(session.state);
auto expected = state_e::RUNNING;
Expand Down Expand Up @@ -2009,6 +2014,7 @@ namespace stream {

session->shutdown_event = mail->event<bool>(mail::shutdown);
session->launch_session_id = launch_session.id;
session->client_cert = launch_session.client_cert;

session->config = config;

Expand Down
1 change: 1 addition & 0 deletions src/stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ namespace stream {
void stop(session_t &session);
void join(session_t &session);
state_e state(session_t &session);
const std::string &client_cert(session_t &session);
} // namespace session
} // namespace stream