Allow end user to configure what ports to listen on
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
# external_ip = 123.456.789.12
|
# external_ip = 123.456.789.12
|
||||||
|
|
||||||
# Set the familly of ports used by Sunshine
|
# Set the familly of ports used by Sunshine
|
||||||
# port = 47984
|
# port = 47989
|
||||||
|
|
||||||
# The private key must be 2048 bits
|
# The private key must be 2048 bits
|
||||||
# pkey = /dir/pkey.pem
|
# pkey = /dir/pkey.pem
|
||||||
@@ -35,7 +35,16 @@
|
|||||||
# lan: Only those in LAN may access /pin
|
# lan: Only those in LAN may access /pin
|
||||||
# wan: Anyone may access /pin
|
# wan: Anyone may access /pin
|
||||||
#
|
#
|
||||||
# origin_pin_allowed = lan
|
# origin_pin_allowed = pc
|
||||||
|
|
||||||
|
# The origin of the remote endpoint address that is not denied for HTTPS Web UI
|
||||||
|
# Could be any of the following values:
|
||||||
|
# pc|lan|wan
|
||||||
|
# pc: Only localhost may access the Web Manager
|
||||||
|
# lan: Only those in LAN may access the Web Manager
|
||||||
|
# wan: Anyone may access the Web Manager
|
||||||
|
#
|
||||||
|
# origin_web_ui_allowed = lan
|
||||||
|
|
||||||
# If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet
|
# If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet
|
||||||
# To enable it, uncomment the following line:
|
# To enable it, uncomment the following line:
|
||||||
|
|||||||
@@ -32,15 +32,15 @@
|
|||||||
</select>
|
</select>
|
||||||
<div class="form-text">The minimum log level printed to standard out</div>
|
<div class="form-text">The minimum log level printed to standard out</div>
|
||||||
</div>
|
</div>
|
||||||
<!--Origin PIN Allowed-->
|
<!--Origin Web UI Allowed-->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="origin_pin_allowed" class="form-label">Origin PIN Allowed</label>
|
<label for="origin_web_ui_allowed" class="form-label">Origin Web UI Allowed</label>
|
||||||
<select id="origin_pin_allowed" class="form-select" v-model="config.origin_pin_allowed">
|
<select id="origin_web_ui_allowed" class="form-select" v-model="config.origin_web_ui_allowed">
|
||||||
<option value="pc">Only localhost may access /pin and Web UI</option>
|
<option value="pc">Only localhost may access Web UI</option>
|
||||||
<option value="lan">Only those in LAN may access /pin and Web UI</option>
|
<option value="lan">Only those in LAN may access Web UI</option>
|
||||||
<option value="wan">Anyone may access /pin and Web UI</option>
|
<option value="wan">Anyone may access Web UI</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="form-text">The origin of the remote endpoint address that is not denied for HTTP method /pin
|
<div class="form-text">The origin of the remote endpoint address that is not denied access to Web UI
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--UPnP-->
|
<!--UPnP-->
|
||||||
@@ -238,6 +238,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="currentTab === 'advanced'" class="config-page">
|
<div v-if="currentTab === 'advanced'" class="config-page">
|
||||||
|
<!--Port familly-->
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="port" class="form-label">Port</label>
|
||||||
|
<input type="number" min="0" max="65529" class="form-control" id="port" placeholder="47989"
|
||||||
|
v-model="config.port">
|
||||||
|
<div class="form-text">
|
||||||
|
Set the familly of ports used by Sunshine
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!--Constant Rate Factor-->
|
<!--Constant Rate Factor-->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="crf" class="form-label">Constant Rate Factor</label>
|
<label for="crf" class="form-label">Constant Rate Factor</label>
|
||||||
@@ -341,6 +350,17 @@
|
|||||||
Store Username/Password seperately from Sunshine's state file.
|
Store Username/Password seperately from Sunshine's state file.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!--Origin PIN Allowed-->
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="origin_pin_allowed" class="form-label">Origin PIN Allowed</label>
|
||||||
|
<select id="origin_pin_allowed" class="form-select" v-model="config.origin_pin_allowed">
|
||||||
|
<option value="pc">Only localhost may access /pin</option>
|
||||||
|
<option value="lan">Only those in LAN may access /pin</option>
|
||||||
|
<option value="wan">Anyone may access /pin</option>
|
||||||
|
</select>
|
||||||
|
<div class="form-text">The origin of the remote endpoint address that is not denied for HTTP method /pin
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!--External IP-->
|
<!--External IP-->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="external_ip" class="form-label">External IP</label>
|
<label for="external_ip" class="form-label">External IP</label>
|
||||||
@@ -517,7 +537,8 @@
|
|||||||
//Populate default values if not present in config
|
//Populate default values if not present in config
|
||||||
this.config.upnp = this.config.upnp || 'disabled';
|
this.config.upnp = this.config.upnp || 'disabled';
|
||||||
this.config.min_log_level = this.config.min_log_level || 2;
|
this.config.min_log_level = this.config.min_log_level || 2;
|
||||||
this.config.origin_pin_allowed = this.config.origin_pin_allowed || "lan";
|
this.config.origin_pin_allowed = this.config.origin_pin_allowed || "pc";
|
||||||
|
this.config.origin_web_ui_allowed = this.config.origin_web_manager_allowed || "lan";
|
||||||
this.config.hevc_mode = this.config.hevc_mode || 0;
|
this.config.hevc_mode = this.config.hevc_mode || 0;
|
||||||
this.config.encoder = this.config.encoder || '';
|
this.config.encoder = this.config.encoder || '';
|
||||||
this.config.nv_preset = this.config.nv_preset || 'default';
|
this.config.nv_preset = this.config.nv_preset || 'default';
|
||||||
|
|||||||
@@ -185,7 +185,9 @@ stream_t stream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
nvhttp_t nvhttp {
|
nvhttp_t nvhttp {
|
||||||
"lan", // origin_pin
|
"pc", // origin_pin
|
||||||
|
"lan", // origin web manager
|
||||||
|
|
||||||
PRIVATE_KEY_FILE,
|
PRIVATE_KEY_FILE,
|
||||||
CERTIFICATE_FILE,
|
CERTIFICATE_FILE,
|
||||||
|
|
||||||
@@ -222,7 +224,8 @@ sunshine_t sunshine {
|
|||||||
{}, // Password
|
{}, // Password
|
||||||
{}, // Password Salt
|
{}, // Password Salt
|
||||||
SUNSHINE_ASSETS_DIR "/sunshine.conf", // config file
|
SUNSHINE_ASSETS_DIR "/sunshine.conf", // config file
|
||||||
{} // cmd args
|
{}, // cmd args
|
||||||
|
47989,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool endline(char ch) {
|
bool endline(char ch) {
|
||||||
@@ -610,6 +613,7 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
|
|||||||
string_f(vars, "virtual_sink", audio.virtual_sink);
|
string_f(vars, "virtual_sink", audio.virtual_sink);
|
||||||
|
|
||||||
string_restricted_f(vars, "origin_pin_allowed", nvhttp.origin_pin_allowed, { "pc"sv, "lan"sv, "wan"sv });
|
string_restricted_f(vars, "origin_pin_allowed", nvhttp.origin_pin_allowed, { "pc"sv, "lan"sv, "wan"sv });
|
||||||
|
string_restricted_f(vars, "origin_web_ui_allowed", nvhttp.origin_web_ui_allowed, { "pc"sv, "lan"sv, "wan"sv });
|
||||||
|
|
||||||
int to = -1;
|
int to = -1;
|
||||||
int_between_f(vars, "ping_timeout", to, { -1, std::numeric_limits<int>::max() });
|
int_between_f(vars, "ping_timeout", to, { -1, std::numeric_limits<int>::max() });
|
||||||
@@ -642,6 +646,10 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
|
|||||||
input.key_repeat_delay = std::chrono::milliseconds { to };
|
input.key_repeat_delay = std::chrono::milliseconds { to };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int port = sunshine.port;
|
||||||
|
int_f(vars, "port"s, port);
|
||||||
|
sunshine.port = (std::uint16_t)port;
|
||||||
|
|
||||||
bool upnp = false;
|
bool upnp = false;
|
||||||
bool_f(vars, "upnp"s, upnp);
|
bool_f(vars, "upnp"s, upnp);
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ struct nvhttp_t {
|
|||||||
// Could be any of the following values:
|
// Could be any of the following values:
|
||||||
// pc|lan|wan
|
// pc|lan|wan
|
||||||
std::string origin_pin_allowed;
|
std::string origin_pin_allowed;
|
||||||
|
std::string origin_web_ui_allowed;
|
||||||
|
|
||||||
std::string pkey; // must be 2048 bits
|
std::string pkey; // must be 2048 bits
|
||||||
std::string cert; // must be signed with a key of 2048 bits
|
std::string cert; // must be signed with a key of 2048 bits
|
||||||
|
|||||||
@@ -30,10 +30,9 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
|
|
||||||
namespace confighttp {
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
constexpr auto PORT_HTTPS = 47990;
|
|
||||||
|
|
||||||
|
namespace confighttp {
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
namespace pt = boost::property_tree;
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
@@ -67,7 +66,7 @@ void print_req(const req_https_t &request) {
|
|||||||
|
|
||||||
void send_unauthorized(resp_https_t response, req_https_t request) {
|
void send_unauthorized(resp_https_t response, req_https_t request) {
|
||||||
auto address = request->remote_endpoint_address();
|
auto address = request->remote_endpoint_address();
|
||||||
BOOST_LOG(info) << '[' << address << "] -- denied"sv;
|
BOOST_LOG(info) << "Web UI: ["sv << address << "] -- not authorized"sv;
|
||||||
const SimpleWeb::CaseInsensitiveMultimap headers {
|
const SimpleWeb::CaseInsensitiveMultimap headers {
|
||||||
{ "WWW-Authenticate", R"(Basic realm="Sunshine Gamestream Host", charset="UTF-8")" }
|
{ "WWW-Authenticate", R"(Basic realm="Sunshine Gamestream Host", charset="UTF-8")" }
|
||||||
};
|
};
|
||||||
@@ -78,8 +77,8 @@ bool authenticate(resp_https_t response, req_https_t request) {
|
|||||||
auto address = request->remote_endpoint_address();
|
auto address = request->remote_endpoint_address();
|
||||||
auto ip_type = net::from_address(address);
|
auto ip_type = net::from_address(address);
|
||||||
|
|
||||||
if(ip_type > http::origin_pin_allowed) {
|
if(ip_type > http::origin_web_ui_allowed) {
|
||||||
BOOST_LOG(info) << '[' << address << "] -- denied"sv;
|
BOOST_LOG(info) << "Web UI: ["sv << address << "] -- denied"sv;
|
||||||
response->write(SimpleWeb::StatusCode::client_error_forbidden);
|
response->write(SimpleWeb::StatusCode::client_error_forbidden);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -455,6 +454,8 @@ void savePin(resp_https_t response, req_https_t request) {
|
|||||||
void start() {
|
void start() {
|
||||||
auto shutdown_event = mail::man->event<bool>(mail::shutdown);
|
auto shutdown_event = mail::man->event<bool>(mail::shutdown);
|
||||||
|
|
||||||
|
auto port_https = map_port(PORT_HTTPS);
|
||||||
|
|
||||||
auto ctx = std::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tls);
|
auto ctx = std::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tls);
|
||||||
ctx->use_certificate_chain_file(config::nvhttp.cert);
|
ctx->use_certificate_chain_file(config::nvhttp.cert);
|
||||||
ctx->use_private_key_file(config::nvhttp.pkey, boost::asio::ssl::context::pem);
|
ctx->use_private_key_file(config::nvhttp.pkey, boost::asio::ssl::context::pem);
|
||||||
@@ -475,14 +476,14 @@ void start() {
|
|||||||
server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp;
|
server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp;
|
||||||
server.config.reuse_address = true;
|
server.config.reuse_address = true;
|
||||||
server.config.address = "0.0.0.0"s;
|
server.config.address = "0.0.0.0"s;
|
||||||
server.config.port = PORT_HTTPS;
|
server.config.port = port_https;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
server.bind();
|
server.bind();
|
||||||
BOOST_LOG(info) << "Configuration UI available at [https://localhost:"sv << PORT_HTTPS << "]";
|
BOOST_LOG(info) << "Configuration UI available at [https://localhost:"sv << port_https << "]";
|
||||||
}
|
}
|
||||||
catch(boost::system::system_error &err) {
|
catch(boost::system::system_error &err) {
|
||||||
BOOST_LOG(fatal) << "Couldn't bind http server to ports ["sv << PORT_HTTPS << "]: "sv << err.what();
|
BOOST_LOG(fatal) << "Couldn't bind http server to ports ["sv << port_https << "]: "sv << err.what();
|
||||||
|
|
||||||
shutdown_event->raise(true);
|
shutdown_event->raise(true);
|
||||||
return;
|
return;
|
||||||
@@ -497,7 +498,7 @@ void start() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG(fatal) << "Couldn't start Configuration HTTP server to ports ["sv << PORT_HTTPS << ", "sv << PORT_HTTPS << "]: "sv << err.what();
|
BOOST_LOG(fatal) << "Couldn't start Configuration HTTPS server to port ["sv << port_https << "]: "sv << err.what();
|
||||||
shutdown_event->raise(true);
|
shutdown_event->raise(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
|
|
||||||
|
|
||||||
namespace confighttp {
|
namespace confighttp {
|
||||||
|
constexpr auto PORT_HTTPS = 1;
|
||||||
void start();
|
void start();
|
||||||
}
|
} // namespace confighttp
|
||||||
|
|
||||||
#endif //SUNSHINE_CONFIGHTTP_H
|
#endif //SUNSHINE_CONFIGHTTP_H
|
||||||
|
|||||||
@@ -35,10 +35,13 @@ bool user_creds_exist(const std::string &file);
|
|||||||
|
|
||||||
std::string unique_id;
|
std::string unique_id;
|
||||||
net::net_e origin_pin_allowed;
|
net::net_e origin_pin_allowed;
|
||||||
|
net::net_e origin_web_ui_allowed;
|
||||||
|
|
||||||
int init() {
|
int init() {
|
||||||
bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE];
|
bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE];
|
||||||
origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed);
|
origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed);
|
||||||
|
origin_web_ui_allowed = net::from_enum_string(config::nvhttp.origin_web_ui_allowed);
|
||||||
|
|
||||||
if(clean_slate) {
|
if(clean_slate) {
|
||||||
unique_id = util::uuid_t::generate().string();
|
unique_id = util::uuid_t::generate().string();
|
||||||
auto dir = std::filesystem::temp_directory_path() / "Sushine"sv;
|
auto dir = std::filesystem::temp_directory_path() / "Sushine"sv;
|
||||||
|
|||||||
@@ -14,5 +14,6 @@ int save_user_creds(
|
|||||||
int reload_user_creds(const std::string &file);
|
int reload_user_creds(const std::string &file);
|
||||||
extern std::string unique_id;
|
extern std::string unique_id;
|
||||||
extern net::net_e origin_pin_allowed;
|
extern net::net_e origin_pin_allowed;
|
||||||
|
extern net::net_e origin_web_ui_allowed;
|
||||||
|
|
||||||
} // namespace http
|
} // namespace http
|
||||||
@@ -270,4 +270,8 @@ int write_file(const char *path, const std::string_view &contents) {
|
|||||||
out << contents;
|
out << contents;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint16_t map_port(int port) {
|
||||||
|
return (std::uint16_t)((int)config::sunshine.port + port);
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,8 @@ void print_help(const char *name);
|
|||||||
std::string read_file(const char *path);
|
std::string read_file(const char *path);
|
||||||
int write_file(const char *path, const std::string_view &contents);
|
int write_file(const char *path, const std::string_view &contents);
|
||||||
|
|
||||||
|
std::uint16_t map_port(int port);
|
||||||
|
|
||||||
namespace mail {
|
namespace mail {
|
||||||
#define MAIL(x) \
|
#define MAIL(x) \
|
||||||
constexpr auto x = std::string_view { #x }
|
constexpr auto x = std::string_view { #x }
|
||||||
|
|||||||
@@ -479,7 +479,7 @@ void pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response,
|
|||||||
auto address = request->remote_endpoint_address();
|
auto address = request->remote_endpoint_address();
|
||||||
auto ip_type = net::from_address(address);
|
auto ip_type = net::from_address(address);
|
||||||
if(ip_type > http::origin_pin_allowed) {
|
if(ip_type > http::origin_pin_allowed) {
|
||||||
BOOST_LOG(info) << '[' << address << "] -- denied"sv;
|
BOOST_LOG(info) << "/pin: ["sv << address << "] -- denied"sv;
|
||||||
|
|
||||||
response->write(SimpleWeb::StatusCode::client_error_forbidden);
|
response->write(SimpleWeb::StatusCode::client_error_forbidden);
|
||||||
|
|
||||||
@@ -759,6 +759,9 @@ void appasset(resp_https_t response, req_https_t request) {
|
|||||||
void start() {
|
void start() {
|
||||||
auto shutdown_event = mail::man->event<bool>(mail::shutdown);
|
auto shutdown_event = mail::man->event<bool>(mail::shutdown);
|
||||||
|
|
||||||
|
auto port_http = map_port(PORT_HTTP);
|
||||||
|
auto port_https = map_port(PORT_HTTPS);
|
||||||
|
|
||||||
bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE];
|
bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE];
|
||||||
|
|
||||||
if(!clean_slate) {
|
if(!clean_slate) {
|
||||||
@@ -836,7 +839,7 @@ void start() {
|
|||||||
|
|
||||||
https_server.config.reuse_address = true;
|
https_server.config.reuse_address = true;
|
||||||
https_server.config.address = "0.0.0.0"s;
|
https_server.config.address = "0.0.0.0"s;
|
||||||
https_server.config.port = PORT_HTTPS;
|
https_server.config.port = port_https;
|
||||||
|
|
||||||
http_server.default_resource = not_found<SimpleWeb::HTTP>;
|
http_server.default_resource = not_found<SimpleWeb::HTTP>;
|
||||||
http_server.resource["^/serverinfo$"]["GET"] = serverinfo<SimpleWeb::HTTP>;
|
http_server.resource["^/serverinfo$"]["GET"] = serverinfo<SimpleWeb::HTTP>;
|
||||||
@@ -845,14 +848,14 @@ void start() {
|
|||||||
|
|
||||||
http_server.config.reuse_address = true;
|
http_server.config.reuse_address = true;
|
||||||
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;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
https_server.bind();
|
https_server.bind();
|
||||||
http_server.bind();
|
http_server.bind();
|
||||||
}
|
}
|
||||||
catch(boost::system::system_error &err) {
|
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();
|
BOOST_LOG(fatal) << "Couldn't bind http server to ports ["sv << port_http << ", "sv << port_http << "]: "sv << err.what();
|
||||||
|
|
||||||
shutdown_event->raise(true);
|
shutdown_event->raise(true);
|
||||||
return;
|
return;
|
||||||
@@ -868,7 +871,7 @@ void start() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG(fatal) << "Couldn't start http server to ports ["sv << PORT_HTTPS << ", "sv << PORT_HTTP << "]: "sv << err.what();
|
BOOST_LOG(fatal) << "Couldn't start http server to ports ["sv << port_https << ", "sv << port_https << "]: "sv << err.what();
|
||||||
shutdown_event->raise(true);
|
shutdown_event->raise(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace nvhttp {
|
namespace nvhttp {
|
||||||
constexpr auto PORT_HTTP = 47989;
|
constexpr auto PORT_HTTP = 0;
|
||||||
constexpr auto PORT_HTTPS = 47984;
|
constexpr auto PORT_HTTPS = -5;
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
bool pin(std::string pin);
|
bool pin(std::string pin);
|
||||||
|
|||||||
@@ -328,7 +328,16 @@ void create_services(avahi::Client *c) {
|
|||||||
if(avahi::entry_group_is_empty(group)) {
|
if(avahi::entry_group_is_empty(group)) {
|
||||||
BOOST_LOG(info) << "Adding avahi service "sv << name.get();
|
BOOST_LOG(info) << "Adding avahi service "sv << name.get();
|
||||||
|
|
||||||
ret = avahi::entry_group_add_service(group, avahi::IF_UNSPEC, avahi::PROTO_UNSPEC, avahi::PublishFlags(0), name.get(), SERVICE_TYPE, nullptr, nullptr, nvhttp::PORT_HTTP, nullptr);
|
ret = avahi::entry_group_add_service(
|
||||||
|
group,
|
||||||
|
avahi::IF_UNSPEC, avahi::PROTO_UNSPEC,
|
||||||
|
avahi::PublishFlags(0),
|
||||||
|
name.get(),
|
||||||
|
SERVICE_TYPE,
|
||||||
|
nullptr, nullptr,
|
||||||
|
map_port(nvhttp::PORT_HTTP),
|
||||||
|
nullptr);
|
||||||
|
|
||||||
if(ret < 0) {
|
if(ret < 0) {
|
||||||
if(ret == avahi::ERR_COLLISION) {
|
if(ret == avahi::ERR_COLLISION) {
|
||||||
// A service name collision with a local service happened. Let's pick a new name
|
// A service name collision with a local service happened. Let's pick a new name
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ static int service(bool enable) {
|
|||||||
|
|
||||||
DNS_SERVICE_INSTANCE instance {};
|
DNS_SERVICE_INSTANCE instance {};
|
||||||
instance.pszInstanceName = name.data();
|
instance.pszInstanceName = name.data();
|
||||||
instance.wPort = nvhttp::PORT_HTTP;
|
instance.wPort = map_port(nvhttp::PORT_HTTP);
|
||||||
instance.pszHostName = host.data();
|
instance.pszHostName = host.data();
|
||||||
|
|
||||||
DNS_SERVICE_REGISTER_REQUEST req {};
|
DNS_SERVICE_REGISTER_REQUEST req {};
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ std::string to_string(T &&t) {
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto RTSP_SETUP_PORT = 48010;
|
|
||||||
|
|
||||||
void free_msg(PRTSP_MESSAGE msg) {
|
void free_msg(PRTSP_MESSAGE msg) {
|
||||||
freeMessage(msg);
|
freeMessage(msg);
|
||||||
|
|
||||||
@@ -505,8 +503,8 @@ void rtpThread() {
|
|||||||
|
|
||||||
server.map("PLAY"sv, &cmd_play);
|
server.map("PLAY"sv, &cmd_play);
|
||||||
|
|
||||||
if(server.bind(RTSP_SETUP_PORT)) {
|
if(server.bind(map_port(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;
|
BOOST_LOG(fatal) << "Couldn't bind RTSP server to port ["sv << map_port(RTSP_SETUP_PORT) << "], likely another process already bound to the port"sv;
|
||||||
shutdown_event->raise(true);
|
shutdown_event->raise(true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "thread_safe.h"
|
#include "thread_safe.h"
|
||||||
|
|
||||||
namespace stream {
|
namespace stream {
|
||||||
|
constexpr auto RTSP_SETUP_PORT = 21;
|
||||||
|
|
||||||
struct launch_session_t {
|
struct launch_session_t {
|
||||||
crypto::aes_t gcm_key;
|
crypto::aes_t gcm_key;
|
||||||
crypto::aes_t iv;
|
crypto::aes_t iv;
|
||||||
|
|||||||
@@ -44,10 +44,6 @@ static const short packetTypes[] = {
|
|||||||
0x0100, // Termination
|
0x0100, // Termination
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr auto VIDEO_STREAM_PORT = 47998;
|
|
||||||
constexpr auto CONTROL_PORT = 47999;
|
|
||||||
constexpr auto AUDIO_STREAM_PORT = 48000;
|
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
namespace sys = boost::system;
|
namespace sys = boost::system;
|
||||||
|
|
||||||
@@ -730,8 +726,12 @@ void audioBroadcastThread(udp::socket &sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int start_broadcast(broadcast_ctx_t &ctx) {
|
int start_broadcast(broadcast_ctx_t &ctx) {
|
||||||
if(ctx.control_server.bind(CONTROL_PORT)) {
|
auto control_port = map_port(CONTROL_PORT);
|
||||||
BOOST_LOG(error) << "Couldn't bind Control server to port ["sv << CONTROL_PORT << "], likely another process already bound to the port"sv;
|
auto video_port = map_port(VIDEO_STREAM_PORT);
|
||||||
|
auto audio_port = map_port(AUDIO_STREAM_PORT);
|
||||||
|
|
||||||
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -744,9 +744,9 @@ int start_broadcast(broadcast_ctx_t &ctx) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.video_sock.bind(udp::endpoint(udp::v4(), VIDEO_STREAM_PORT), ec);
|
ctx.video_sock.bind(udp::endpoint(udp::v4(), video_port), ec);
|
||||||
if(ec) {
|
if(ec) {
|
||||||
BOOST_LOG(fatal) << "Couldn't bind Video server to port ["sv << VIDEO_STREAM_PORT << "]: "sv << ec.message();
|
BOOST_LOG(fatal) << "Couldn't bind Video server to port ["sv << video_port << "]: "sv << ec.message();
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -758,9 +758,9 @@ int start_broadcast(broadcast_ctx_t &ctx) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.audio_sock.bind(udp::endpoint(udp::v4(), AUDIO_STREAM_PORT), ec);
|
ctx.audio_sock.bind(udp::endpoint(udp::v4(), audio_port), ec);
|
||||||
if(ec) {
|
if(ec) {
|
||||||
BOOST_LOG(fatal) << "Couldn't bind Audio server to port ["sv << AUDIO_STREAM_PORT << "]: "sv << ec.message();
|
BOOST_LOG(fatal) << "Couldn't bind Audio server to port ["sv << audio_port << "]: "sv << ec.message();
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,10 @@
|
|||||||
#include "video.h"
|
#include "video.h"
|
||||||
|
|
||||||
namespace stream {
|
namespace stream {
|
||||||
|
constexpr auto VIDEO_STREAM_PORT = 9;
|
||||||
|
constexpr auto CONTROL_PORT = 10;
|
||||||
|
constexpr auto AUDIO_STREAM_PORT = 11;
|
||||||
|
|
||||||
struct session_t;
|
struct session_t;
|
||||||
struct config_t {
|
struct config_t {
|
||||||
audio::config_t audio;
|
audio::config_t audio;
|
||||||
|
|||||||
@@ -2,14 +2,19 @@
|
|||||||
#include <miniupnpc/upnpcommands.h>
|
#include <miniupnpc/upnpcommands.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "confighttp.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "network.h"
|
||||||
|
#include "nvhttp.h"
|
||||||
|
#include "rtsp.h"
|
||||||
|
#include "stream.h"
|
||||||
#include "upnp.h"
|
#include "upnp.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
namespace upnp {
|
namespace upnp {
|
||||||
constexpr auto INET6_ADDRSTRLEN = 46;
|
constexpr auto INET6_ADDRESS_STRLEN = 46;
|
||||||
|
|
||||||
constexpr auto IPv4 = 0;
|
constexpr auto IPv4 = 0;
|
||||||
constexpr auto IPv6 = 1;
|
constexpr auto IPv6 = 1;
|
||||||
@@ -21,9 +26,6 @@ KITTY_USING_MOVE_T(urls_t, UPNPUrls, , {
|
|||||||
});
|
});
|
||||||
|
|
||||||
struct mapping_t {
|
struct mapping_t {
|
||||||
mapping_t(std::string &&wan, std::string &&lan, std::string &&description, bool tcp)
|
|
||||||
: port { std::move(wan), std::move(lan) }, description { std::move(description) }, tcp { tcp } {}
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
std::string wan;
|
std::string wan;
|
||||||
std::string lan;
|
std::string lan;
|
||||||
@@ -33,16 +35,6 @@ struct mapping_t {
|
|||||||
bool tcp;
|
bool tcp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::vector<mapping_t> mappings {
|
|
||||||
{ "48010"s, "48010"s, "RTSP setup port"s, false },
|
|
||||||
{ "47998"s, "47998"s, "Video stream port"s, false },
|
|
||||||
{ "47999"s, "47998"s, "Control stream port"s, false },
|
|
||||||
{ "48000"s, "48000"s, "Audio stream port"s, false },
|
|
||||||
{ "47989"s, "47989"s, "Gamestream http port"s, true },
|
|
||||||
{ "47984"s, "47984"s, "Gamestream https port"s, true },
|
|
||||||
{ "47990"s, "47990"s, "Sunshine Web Manager port"s, true },
|
|
||||||
};
|
|
||||||
|
|
||||||
void unmap(
|
void unmap(
|
||||||
const urls_t &urls,
|
const urls_t &urls,
|
||||||
const IGDdatas &data,
|
const IGDdatas &data,
|
||||||
@@ -69,19 +61,18 @@ void unmap(
|
|||||||
class deinit_t : public platf::deinit_t {
|
class deinit_t : public platf::deinit_t {
|
||||||
public:
|
public:
|
||||||
using iter_t = std::vector<mapping_t>::const_reverse_iterator;
|
using iter_t = std::vector<mapping_t>::const_reverse_iterator;
|
||||||
deinit_t(urls_t &&urls, IGDdatas data, iter_t begin, iter_t end)
|
deinit_t(urls_t &&urls, IGDdatas data, std::vector<mapping_t> &&mapping)
|
||||||
: urls { std::move(urls) }, data { data }, begin { begin }, end { end } {}
|
: urls { std::move(urls) }, data { data }, mapping { std::move(mapping) } {}
|
||||||
|
|
||||||
~deinit_t() {
|
~deinit_t() {
|
||||||
BOOST_LOG(info) << "Unmapping UPNP ports..."sv;
|
BOOST_LOG(info) << "Unmapping UPNP ports..."sv;
|
||||||
unmap(urls, data, begin, end);
|
unmap(urls, data, std::rbegin(mapping), std::rend(mapping));
|
||||||
}
|
}
|
||||||
|
|
||||||
urls_t urls;
|
urls_t urls;
|
||||||
IGDdatas data;
|
IGDdatas data;
|
||||||
|
|
||||||
iter_t begin;
|
std::vector<mapping_t> mapping;
|
||||||
iter_t end;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string_view status_string(int status) {
|
static std::string_view status_string(int status) {
|
||||||
@@ -111,8 +102,8 @@ std::unique_ptr<platf::deinit_t> start() {
|
|||||||
BOOST_LOG(debug) << "Found device: "sv << dev->descURL;
|
BOOST_LOG(debug) << "Found device: "sv << dev->descURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<char, INET6_ADDRSTRLEN> lan_addr;
|
std::array<char, INET6_ADDRESS_STRLEN> lan_addr;
|
||||||
std::array<char, INET6_ADDRSTRLEN> wan_addr;
|
std::array<char, INET6_ADDRESS_STRLEN> wan_addr;
|
||||||
|
|
||||||
urls_t urls;
|
urls_t urls;
|
||||||
IGDdatas data;
|
IGDdatas data;
|
||||||
@@ -139,6 +130,28 @@ std::unique_ptr<platf::deinit_t> start() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto rtsp = std::to_string(map_port(stream::RTSP_SETUP_PORT));
|
||||||
|
auto video = std::to_string(map_port(stream::VIDEO_STREAM_PORT));
|
||||||
|
auto audio = std::to_string(map_port(stream::AUDIO_STREAM_PORT));
|
||||||
|
auto control = std::to_string(map_port(stream::CONTROL_PORT));
|
||||||
|
auto gs_http = std::to_string(map_port(nvhttp::PORT_HTTP));
|
||||||
|
auto gs_https = std::to_string(map_port(nvhttp::PORT_HTTPS));
|
||||||
|
auto wm_http = std::to_string(map_port(confighttp::PORT_HTTPS));
|
||||||
|
|
||||||
|
std::vector<mapping_t> mappings {
|
||||||
|
{ rtsp, rtsp, "RTSP setup port"s, false },
|
||||||
|
{ video, video, "Video stream port"s, false },
|
||||||
|
{ audio, audio, "Control stream port"s, false },
|
||||||
|
{ control, control, "Audio stream port"s, false },
|
||||||
|
{ gs_http, gs_http, "Gamestream http port"s, true },
|
||||||
|
{ gs_https, gs_https, "Gamestream https port"s, true },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only map port for the Web Manager if it is configured to accept connection from WAN
|
||||||
|
if(net::from_enum_string(config::nvhttp.origin_web_ui_allowed) > net::LAN) {
|
||||||
|
mappings.emplace_back(mapping_t { wm_http, wm_http, "Sunshine Web UI port"s, true });
|
||||||
|
}
|
||||||
|
|
||||||
auto it = std::begin(mappings);
|
auto it = std::begin(mappings);
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
@@ -166,6 +179,6 @@ std::unique_ptr<platf::deinit_t> start() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_unique<deinit_t>(std::move(urls), data, std::rbegin(mappings), std::rend(mappings));
|
return std::make_unique<deinit_t>(std::move(urls), data, std::move(mappings));
|
||||||
}
|
}
|
||||||
} // namespace upnp
|
} // namespace upnp
|
||||||
Reference in New Issue
Block a user