mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-03-30 16:20:40 +00:00
Exit gracefully if a port is bound by another process
This commit is contained in:
parent
1a233ca4aa
commit
e10c9a1fa1
@ -832,8 +832,18 @@ void start(std::shared_ptr<safe::signal_t> shutdown_event) {
|
|||||||
http_server.config.address = "0.0.0.0"s;
|
http_server.config.address = "0.0.0.0"s;
|
||||||
http_server.config.port = PORT_HTTP;
|
http_server.config.port = PORT_HTTP;
|
||||||
|
|
||||||
std::thread ssl { &https_server_t::start, &https_server };
|
try {
|
||||||
std::thread tcp { &http_server_t::start, &http_server };
|
https_server.bind();
|
||||||
|
http_server.bind();
|
||||||
|
} catch(boost::system::system_error &err) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't bind http server to ports ["sv << PORT_HTTPS << ", "sv << PORT_HTTP << "]: "sv << err.what();
|
||||||
|
|
||||||
|
shutdown_event->raise(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread ssl { &https_server_t::accept_and_run, &https_server };
|
||||||
|
std::thread tcp { &http_server_t::accept_and_run, &http_server };
|
||||||
|
|
||||||
// Wait for any event
|
// Wait for any event
|
||||||
shutdown_event->view();
|
shutdown_event->view();
|
||||||
|
@ -54,11 +54,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(std::uint16_t port) {
|
int bind(std::uint16_t port) {
|
||||||
_session_slots.resize(config::stream.channels);
|
_session_slots.resize(config::stream.channels);
|
||||||
_slot_count = config::stream.channels;
|
_slot_count = config::stream.channels;
|
||||||
|
|
||||||
_host = net::host_create(_addr, 1, port);
|
_host = net::host_create(_addr, 1, port);
|
||||||
|
|
||||||
|
return !(bool)_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_raise(launch_session_t launch_session) {
|
void session_raise(launch_session_t launch_session) {
|
||||||
@ -157,16 +159,21 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool accept(const std::shared_ptr<session_t> &session) {
|
void clear(std::shared_ptr<session_t> *session_p) {
|
||||||
|
session_p->reset();
|
||||||
|
|
||||||
|
++_slot_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<session_t> *accept(std::shared_ptr<session_t> &session) {
|
||||||
for(auto &slot : _session_slots) {
|
for(auto &slot : _session_slots) {
|
||||||
if(!slot) {
|
if(!slot) {
|
||||||
slot = session;
|
slot = session;
|
||||||
|
return &slot;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
net::host_t::pointer host() const {
|
net::host_t::pointer host() const {
|
||||||
@ -412,14 +419,22 @@ void cmd_announce(rtsp_server_t *server, net::peer_t peer, msg_t &&req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto session = session::alloc(config, launch_session->gcm_key, launch_session->iv);
|
auto session = session::alloc(config, launch_session->gcm_key, launch_session->iv);
|
||||||
if(!server->accept(session)) {
|
|
||||||
|
auto slot = server->accept(session);
|
||||||
|
if(!slot) {
|
||||||
BOOST_LOG(info) << "Ran out of slots for client from ["sv << ']';
|
BOOST_LOG(info) << "Ran out of slots for client from ["sv << ']';
|
||||||
|
|
||||||
respond(server->host(), peer, &option, 503, "Service Unavailable", req->sequenceNumber, {});
|
respond(server->host(), peer, &option, 503, "Service Unavailable", req->sequenceNumber, {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
session::start(*session, platf::from_sockaddr((sockaddr*)&peer->address.address));
|
if(session::start(*session, platf::from_sockaddr((sockaddr*)&peer->address.address))) {
|
||||||
|
BOOST_LOG(error) << "Failed to start a streaming session"sv;
|
||||||
|
|
||||||
|
server->clear(slot);
|
||||||
|
respond(server->host(), peer, &option, 500, "Internal Server Error", req->sequenceNumber, {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
respond(server->host(), peer, &option, 200, "OK", req->sequenceNumber, {});
|
respond(server->host(), peer, &option, 200, "OK", req->sequenceNumber, {});
|
||||||
}
|
}
|
||||||
@ -444,7 +459,13 @@ void rtpThread(std::shared_ptr<safe::signal_t> shutdown_event) {
|
|||||||
|
|
||||||
server.map("PLAY"sv, &cmd_play);
|
server.map("PLAY"sv, &cmd_play);
|
||||||
|
|
||||||
server.bind(RTSP_SETUP_PORT);
|
if(server.bind(RTSP_SETUP_PORT)) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't bind RTSP server to port ["sv << RTSP_SETUP_PORT << "], likely another process already bound to the port"sv;
|
||||||
|
shutdown_event->raise(true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while(!shutdown_event->peek()) {
|
while(!shutdown_event->peek()) {
|
||||||
server.iterate(std::min(500ms, config::stream.ping_timeout));
|
server.iterate(std::min(500ms, config::stream.ping_timeout));
|
||||||
|
|
||||||
|
@ -99,10 +99,11 @@ static inline void while_starting_do_nothing(std::atomic<session::state_e> &stat
|
|||||||
|
|
||||||
class control_server_t {
|
class control_server_t {
|
||||||
public:
|
public:
|
||||||
control_server_t(control_server_t &&) noexcept = default;
|
int bind(std::uint16_t port) {
|
||||||
control_server_t &operator=(control_server_t &&) noexcept = default;
|
_host = net::host_create(_addr, config::stream.channels, port);
|
||||||
|
|
||||||
explicit control_server_t(std::uint16_t port) : _host { net::host_create(_addr, config::stream.channels, port) } {}
|
return !(bool)_host;
|
||||||
|
}
|
||||||
|
|
||||||
void emplace_addr_to_session(const std::string &addr, session_t &session) {
|
void emplace_addr_to_session(const std::string &addr, session_t &session) {
|
||||||
auto lg = _map_addr_session.lock();
|
auto lg = _map_addr_session.lock();
|
||||||
@ -160,9 +161,9 @@ struct broadcast_ctx_t {
|
|||||||
|
|
||||||
asio::io_service io;
|
asio::io_service io;
|
||||||
|
|
||||||
udp::socket video_sock { io, udp::endpoint(udp::v4(), VIDEO_STREAM_PORT) };
|
udp::socket video_sock { io };
|
||||||
udp::socket audio_sock { io, udp::endpoint(udp::v4(), AUDIO_STREAM_PORT) };
|
udp::socket audio_sock { io };
|
||||||
control_server_t control_server { CONTROL_PORT };
|
control_server_t control_server;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct session_t {
|
struct session_t {
|
||||||
@ -718,6 +719,41 @@ void audioBroadcastThread(safe::signal_t *shutdown_event, udp::socket &sock, aud
|
|||||||
}
|
}
|
||||||
|
|
||||||
int start_broadcast(broadcast_ctx_t &ctx) {
|
int start_broadcast(broadcast_ctx_t &ctx) {
|
||||||
|
if(ctx.control_server.bind(CONTROL_PORT)) {
|
||||||
|
BOOST_LOG(error) << "Couldn't bind Control server to port ["sv << CONTROL_PORT << "], likely another process already bound to the port"sv;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::system::error_code ec;
|
||||||
|
ctx.video_sock.open(udp::v4(), ec);
|
||||||
|
if(ec) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't open socket for Video server: "sv << ec.message();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.video_sock.bind(udp::endpoint(udp::v4(), VIDEO_STREAM_PORT), ec);
|
||||||
|
if(ec) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't bind Video server to port ["sv << VIDEO_STREAM_PORT << "]: "sv << ec.message();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.audio_sock.open(udp::v4(), ec);
|
||||||
|
if(ec) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't open socket for Audio server: "sv << ec.message();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.audio_sock.bind(udp::endpoint(udp::v4(), AUDIO_STREAM_PORT), ec);
|
||||||
|
if(ec) {
|
||||||
|
BOOST_LOG(fatal) << "Couldn't bind Audio server to port ["sv << AUDIO_STREAM_PORT << "]: "sv << ec.message();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.video_packets = std::make_shared<video::packet_queue_t::element_type>(30);
|
ctx.video_packets = std::make_shared<video::packet_queue_t::element_type>(30);
|
||||||
ctx.audio_packets = std::make_shared<audio::packet_queue_t::element_type>(30);
|
ctx.audio_packets = std::make_shared<audio::packet_queue_t::element_type>(30);
|
||||||
ctx.message_queue_queue = std::make_shared<message_queue_queue_t::element_type>(30);
|
ctx.message_queue_queue = std::make_shared<message_queue_queue_t::element_type>(30);
|
||||||
@ -861,10 +897,14 @@ void join(session_t &session) {
|
|||||||
BOOST_LOG(debug) << "Session ended"sv;
|
BOOST_LOG(debug) << "Session ended"sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start(session_t &session, const std::string &addr_string) {
|
int start(session_t &session, const std::string &addr_string) {
|
||||||
session.input = input::alloc();
|
session.input = input::alloc();
|
||||||
|
|
||||||
session.broadcast_ref = broadcast.ref();
|
session.broadcast_ref = broadcast.ref();
|
||||||
|
if(!session.broadcast_ref) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
session.broadcast_ref->control_server.emplace_addr_to_session(addr_string, session);
|
session.broadcast_ref->control_server.emplace_addr_to_session(addr_string, session);
|
||||||
|
|
||||||
session.pingTimeout = std::chrono::steady_clock::now() + config::stream.ping_timeout;
|
session.pingTimeout = std::chrono::steady_clock::now() + config::stream.ping_timeout;
|
||||||
@ -873,6 +913,8 @@ void start(session_t &session, const std::string &addr_string) {
|
|||||||
session.videoThread = std::thread {videoThread, &session, addr_string};
|
session.videoThread = std::thread {videoThread, &session, addr_string};
|
||||||
|
|
||||||
session.state.store(state_e::RUNNING, std::memory_order_relaxed);
|
session.state.store(state_e::RUNNING, std::memory_order_relaxed);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<session_t> alloc(config_t &config, crypto::aes_t &gcm_key, crypto::aes_t &iv) {
|
std::shared_ptr<session_t> alloc(config_t &config, crypto::aes_t &gcm_key, crypto::aes_t &iv) {
|
||||||
|
@ -31,7 +31,7 @@ enum class state_e : int {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<session_t> alloc(config_t &config, crypto::aes_t &gcm_key, crypto::aes_t &iv);
|
std::shared_ptr<session_t> alloc(config_t &config, crypto::aes_t &gcm_key, crypto::aes_t &iv);
|
||||||
void start(session_t &session, const std::string &addr_string);
|
int start(session_t &session, const std::string &addr_string);
|
||||||
void stop(session_t &session);
|
void stop(session_t &session);
|
||||||
void join(session_t &session);
|
void join(session_t &session);
|
||||||
state_e state(session_t &session);
|
state_e state(session_t &session);
|
||||||
|
@ -311,13 +311,15 @@ public:
|
|||||||
[[nodiscard]] ptr_t ref() {
|
[[nodiscard]] ptr_t ref() {
|
||||||
std::lock_guard lg { _lock };
|
std::lock_guard lg { _lock };
|
||||||
|
|
||||||
if(!_count++) {
|
if(!_count) {
|
||||||
new(_object_buf.data()) element_type;
|
new(_object_buf.data()) element_type;
|
||||||
if(_construct(*reinterpret_cast<element_type*>(_object_buf.data()))) {
|
if(_construct(*reinterpret_cast<element_type*>(_object_buf.data()))) {
|
||||||
return ptr_t { nullptr };
|
return ptr_t { nullptr };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++_count;
|
||||||
|
|
||||||
return ptr_t { this };
|
return ptr_t { this };
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user