diff --git a/assets/sunshine.conf b/assets/sunshine.conf
index 14e3dc58..87fc3d29 100644
--- a/assets/sunshine.conf
+++ b/assets/sunshine.conf
@@ -1,6 +1,9 @@
-# If no external IP address is given, the local IP address is used
+# If no external IP address is given, Sunshine will attempt to automatically detect external ip-address
# external_ip = 123.456.789.12
+# Set the familly of ports used by Sunshine
+# port = 47984
+
# The private key must be 2048 bits
# pkey = /dir/pkey.pem
@@ -34,6 +37,10 @@
#
# origin_pin_allowed = lan
+# If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet
+# To enable it, uncomment the following line:
+# upnp = on
+
# The file where current state of Sunshine is stored
# file_state = sunshine_state.json
diff --git a/assets/web/config.html b/assets/web/config.html
index d9e8628f..23ac5d31 100644
--- a/assets/web/config.html
+++ b/assets/web/config.html
@@ -43,12 +43,14 @@
The origin of the remote endpoint address that is not denied for HTTP method /pin
-
+
-
-
-
If no external IP address is given, the local IP address is used
+
+
+
Automatically configure port forwarding
@@ -339,6 +341,14 @@
Store Username/Password seperately from Sunshine's state file.
+
+
+
+
+
If no external IP address is given, Sunshine will automatically detect external
+ IP
+
@@ -505,6 +515,7 @@
delete this.config.status;
delete this.config.platform;
//Populate default values if not present in config
+ this.config.upnp = this.config.upnp || 'disabled';
this.config.min_log_level = this.config.min_log_level || 2;
this.config.origin_pin_allowed = this.config.origin_pin_allowed || "lan";
this.config.hevc_mode = this.config.hevc_mode || 0;
@@ -557,4 +568,4 @@
font-size: 12px;
font-weight: bold;
}
-
+
\ No newline at end of file
diff --git a/sunshine/config.cpp b/sunshine/config.cpp
index ad86ef09..f02da2aa 100644
--- a/sunshine/config.cpp
+++ b/sunshine/config.cpp
@@ -446,9 +446,12 @@ bool to_bool(std::string &boolean) {
return boolean == "true"sv ||
boolean == "yes"sv ||
boolean == "enable"sv ||
+ boolean == "enabled"sv ||
+ boolean == "on"sv ||
(std::find(std::begin(boolean), std::end(boolean), '1') != std::end(boolean));
}
-void bool_f(std::unordered_map &vars, const std::string &name, int &input) {
+
+void bool_f(std::unordered_map &vars, const std::string &name, bool &input) {
std::string tmp;
string_f(vars, name, tmp);
@@ -456,7 +459,7 @@ void bool_f(std::unordered_map &vars, const std::strin
return;
}
- input = to_bool(tmp) ? 1 : 0;
+ input = to_bool(tmp);
}
void double_f(std::unordered_map &vars, const std::string &name, double &input) {
@@ -553,7 +556,7 @@ int apply_flags(const char *line) {
config::sunshine.flags[config::flag::FORCE_VIDEO_HEADER_REPLACE].flip();
break;
case 'p':
- config::sunshine.flags[config::flag::CONST_PIN].flip();
+ config::sunshine.flags[config::flag::UPNP].flip();
break;
default:
std::cout << "Warning: Unrecognized flag: ["sv << *line << ']' << std::endl;
@@ -639,6 +642,13 @@ void apply_config(std::unordered_map &&vars) {
input.key_repeat_delay = std::chrono::milliseconds { to };
}
+ bool upnp = false;
+ bool_f(vars, "upnp"s, upnp);
+
+ if(upnp) {
+ config::sunshine.flags[config::flag::UPNP].flip();
+ }
+
std::string log_level_string;
string_restricted_f(vars, "min_log_level", log_level_string, { "verbose"sv, "debug"sv, "info"sv, "warning"sv, "error"sv, "fatal"sv, "none"sv });
diff --git a/sunshine/config.h b/sunshine/config.h
index 221df6f9..59a0ebdc 100644
--- a/sunshine/config.h
+++ b/sunshine/config.h
@@ -83,6 +83,7 @@ enum flag_e : std::size_t {
PIN_STDIN = 0, // Read PIN from stdin instead of http
FRESH_STATE, // Do not load or save state
FORCE_VIDEO_HEADER_REPLACE, // force replacing headers inside video data
+ UPNP, // Try Universal Plug 'n Play
CONST_PIN, // Use "universal" pin
FLAG_SIZE
};
@@ -104,6 +105,8 @@ struct sunshine_t {
int argc;
char **argv;
} cmd;
+
+ std::uint16_t port;
};
extern video_t video;
diff --git a/sunshine/confighttp.cpp b/sunshine/confighttp.cpp
index ed0a3b88..f568b693 100644
--- a/sunshine/confighttp.cpp
+++ b/sunshine/confighttp.cpp
@@ -15,7 +15,7 @@
#include
#include
-#include
+#include
#include
#include "config.h"
diff --git a/sunshine/main.cpp b/sunshine/main.cpp
index bfbcbf69..d602c192 100644
--- a/sunshine/main.cpp
+++ b/sunshine/main.cpp
@@ -61,14 +61,16 @@ void print_help(const char *name) {
<< "Usage: "sv << name << " [options] [/path/to/configuration_file] [--cmd]"sv << std::endl
<< " Any configurable option can be overwritten with: \"name=value\""sv << std::endl
<< std::endl
- << " --help | print help"sv << std::endl
+ << " --help | print help"sv << std::endl
<< " --creds username password | set user credentials for the Web manager" << std::endl
<< std::endl
<< " flags"sv << std::endl
<< " -0 | Read PIN from stdin"sv << std::endl
<< " -1 | Do not load previously saved state and do retain any state after shutdown"sv << std::endl
<< " | Effectively starting as if for the first time without overwriting any pairings with your devices"sv << std::endl
- << " -2 | Force replacement of headers in video stream" << std::endl;
+ << " -2 | Force replacement of headers in video stream" << std::endl
+ << " -p | Enable/Disable UPnP" << std::endl
+ << std::endl;
}
namespace help {
diff --git a/sunshine/nvhttp.cpp b/sunshine/nvhttp.cpp
index c2beaa4f..cc7b6a07 100644
--- a/sunshine/nvhttp.cpp
+++ b/sunshine/nvhttp.cpp
@@ -30,8 +30,8 @@
#include "utility.h"
#include "uuid.h"
-namespace nvhttp {
using namespace std::literals;
+namespace nvhttp {
constexpr auto VERSION = "7.1.400.0";
constexpr auto GFE_VERSION = "3.12.0.1";
diff --git a/sunshine/nvhttp.h b/sunshine/nvhttp.h
index dcd39461..9e51171a 100644
--- a/sunshine/nvhttp.h
+++ b/sunshine/nvhttp.h
@@ -6,9 +6,6 @@
#define SUNSHINE_NVHTTP_H
#include "thread_safe.h"
-#include
-#include
-#include
#include
namespace nvhttp {
diff --git a/sunshine/upnp.cpp b/sunshine/upnp.cpp
index 58fd0102..117a5615 100644
--- a/sunshine/upnp.cpp
+++ b/sunshine/upnp.cpp
@@ -73,6 +73,7 @@ public:
: urls { std::move(urls) }, data { data }, begin { begin }, end { end } {}
~deinit_t() {
+ BOOST_LOG(info) << "Unmapping UPNP ports..."sv;
unmap(urls, data, begin, end);
}
@@ -134,6 +135,10 @@ std::unique_ptr start() {
}
}
+ if(!config::sunshine.flags[config::flag::UPNP]) {
+ return nullptr;
+ }
+
auto it = std::begin(mappings);
status = 0;