From c0116e0cdd2a66c8f53d53460188413adc3a530f Mon Sep 17 00:00:00 2001 From: loki Date: Wed, 18 Mar 2020 21:12:05 +0100 Subject: [PATCH] Don't quit application when a session still running --- sunshine/nvhttp.cpp | 37 ++++++++++++++++++++++++------ sunshine/rtsp.cpp | 56 +++++++++++++++++++++++++++++++++------------ sunshine/rtsp.h | 3 ++- 3 files changed, 73 insertions(+), 23 deletions(-) diff --git a/sunshine/nvhttp.cpp b/sunshine/nvhttp.cpp index 53100688..4d74fd78 100644 --- a/sunshine/nvhttp.cpp +++ b/sunshine/nvhttp.cpp @@ -527,6 +527,15 @@ void launch(resp_https_t response, req_https_t request) { response->write(data.str()); }); + BOOST_LOG(fatal) << stream::session_count(); + + if(stream::session_count() == config::stream.channels) { + tree.put("root.resume", 0); + tree.put("root..status_code", 503); + + return; + } + auto args = request->parse_query_string(); auto appid = util::from_view(args.at("appid")) -1; @@ -558,7 +567,7 @@ void launch(resp_https_t response, req_https_t request) { auto next = std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv)); std::fill(next, std::end(launch_session.iv), 0); - stream::launch_event.raise(launch_session); + stream::launch_session_raise(launch_session); tree.put("root..status_code", 200); tree.put("root.gamesession", 1); @@ -575,6 +584,16 @@ void resume(resp_https_t response, req_https_t request) { response->write(data.str()); }); + // It is possible that due a race condition that this if-statement gives a false negative, + // that is automatically resolved in rtsp_server_t + if(stream::session_count() == config::stream.channels) { + BOOST_LOG(fatal) << stream::session_count(); + tree.put("root.resume", 0); + tree.put("root..status_code", 503); + + return; + } + auto current_appid = proc::proc.running(); if(current_appid == -1) { tree.put("root.resume", 0); @@ -594,7 +613,7 @@ void resume(resp_https_t response, req_https_t request) { auto next = std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv)); std::fill(next, std::end(launch_session.iv), 0); - stream::launch_event.raise(launch_session); + stream::launch_session_raise(launch_session); tree.put("root..status_code", 200); tree.put("root.resume", 1); @@ -611,17 +630,21 @@ void cancel(resp_https_t response, req_https_t request) { response->write(data.str()); }); - if(proc::proc.running() == -1) { - tree.put("root.cancel", 1); - tree.put("root..status_code", 200); + // It is possible that due a race condition that this if-statement gives a false positive, + // the client should try again + if(stream::session_count() != 0) { + tree.put("root.resume", 0); + tree.put("root..status_code", 503); return; } - proc::proc.terminate(); - tree.put("root.cancel", 1); tree.put("root..status_code", 200); + + if(proc::proc.running() != -1) { + proc::proc.terminate(); + } } void appasset(resp_https_t response, req_https_t request) { diff --git a/sunshine/rtsp.cpp b/sunshine/rtsp.cpp index d16aef73..d0a1d1a7 100644 --- a/sunshine/rtsp.cpp +++ b/sunshine/rtsp.cpp @@ -43,20 +43,31 @@ class rtsp_server_t; using msg_t = util::safe_ptr; using cmd_func_t = std::function; -safe::event_t launch_event; - void print_msg(PRTSP_MESSAGE msg); void cmd_not_found(net::host_t::pointer host, net::peer_t peer, msg_t&& req); class rtsp_server_t { public: - rtsp_server_t(rtsp_server_t &&) noexcept = default; - rtsp_server_t &operator=(rtsp_server_t &&) noexcept = default; - - explicit rtsp_server_t(std::uint16_t port) : _session_slots (config::stream.channels), _host {net::host_create(_addr, 1, port) } {} - ~rtsp_server_t() { - stop(); + if(_host) { + clear(); + } + } + + void bind(std::uint16_t port) { + _session_slots.resize(config::stream.channels); + _slot_count = config::stream.channels; + + _host = net::host_create(_addr, 1, port); + } + + void session_raise(launch_session_t launch_session) { + --_slot_count; + launch_event.raise(launch_session); + } + + int session_count() const { + return config::stream.channels - _slot_count; } template @@ -127,13 +138,15 @@ public: _map_cmd_cb.emplace(type, std::move(cb)); } - void stop(bool all = true) { + void clear(bool all = true) { for(auto &slot : _session_slots) { if (slot && (all || session::state(*slot) == session::state_e::STOPPING)) { session::stop(*slot); session::join(*slot); slot.reset(); + + ++_slot_count; } } @@ -159,6 +172,9 @@ public: net::host_t::pointer host() const { return _host.get(); } + + safe::event_t launch_event; + private: // named _queue_packet because I want to make it an actual queue @@ -169,10 +185,21 @@ private: std::vector> _session_slots; + int _slot_count; ENetAddress _addr; net::host_t _host; }; +rtsp_server_t server; + +void launch_session_raise(launch_session_t launch_session) { + server.session_raise(launch_session); +} + +int session_count() { + return server.session_count(); +} + void respond(net::host_t::pointer host, net::peer_t peer, msg_t &resp) { auto payload = std::make_pair(resp->payload, resp->payloadLength); @@ -297,13 +324,13 @@ void cmd_announce(rtsp_server_t *server, net::peer_t peer, msg_t &&req) { auto seqn_str = to_string(req->sequenceNumber); option.content = const_cast(seqn_str.c_str()); - if(!launch_event.peek()) { + if(!server->launch_event.peek()) { // /launch has not been used respond(server->host(), peer, &option, 503, "Service Unavailable", req->sequenceNumber, {}); return; } - auto launch_session { launch_event.pop() }; + auto launch_session { server->launch_event.pop() }; std::string_view payload { req->payload, (size_t)req->payloadLength }; @@ -410,8 +437,6 @@ void cmd_play(rtsp_server_t *server, net::peer_t peer, msg_t &&req) { } void rtpThread(std::shared_ptr shutdown_event) { - rtsp_server_t server(RTSP_SETUP_PORT); - server.map("OPTIONS"sv, &cmd_option); server.map("DESCRIBE"sv, &cmd_describe); server.map("SETUP"sv, &cmd_setup); @@ -419,15 +444,16 @@ void rtpThread(std::shared_ptr shutdown_event) { server.map("PLAY"sv, &cmd_play); + server.bind(RTSP_SETUP_PORT); while(!shutdown_event->peek()) { server.iterate(std::min(500ms, config::stream.ping_timeout)); if(broadcast_shutdown_event.peek()) { - server.stop(); + server.clear(); } else { // cleanup all stopped sessions - server.stop(false); + server.clear(false); } } } diff --git a/sunshine/rtsp.h b/sunshine/rtsp.h index b75d3b80..ac60e8d6 100644 --- a/sunshine/rtsp.h +++ b/sunshine/rtsp.h @@ -16,7 +16,8 @@ struct launch_session_t { crypto::aes_t iv; }; -extern safe::event_t launch_event; +void launch_session_raise(launch_session_t launch_session); +int session_count(); void rtpThread(std::shared_ptr shutdown_event);