2019-12-03 22:19:00 +00:00
|
|
|
#include <fstream>
|
2020-01-09 21:02:01 +00:00
|
|
|
#include <iostream>
|
2019-12-03 22:19:00 +00:00
|
|
|
#include <functional>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
2020-01-18 04:03:50 +00:00
|
|
|
#include <boost/asio.hpp>
|
|
|
|
|
2019-12-03 22:19:00 +00:00
|
|
|
#include "utility.h"
|
2019-12-03 19:23:33 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#define CA_DIR SUNSHINE_ASSETS_DIR "/demoCA"
|
|
|
|
#define PRIVATE_KEY_FILE CA_DIR "/cakey.pem"
|
|
|
|
#define CERTIFICATE_FILE CA_DIR "/cacert.pem"
|
|
|
|
|
2019-12-16 21:02:21 +00:00
|
|
|
#define APPS_JSON SUNSHINE_ASSETS_DIR "/apps.json"
|
2019-12-03 19:23:33 +00:00
|
|
|
namespace config {
|
|
|
|
using namespace std::literals;
|
|
|
|
video_t video {
|
|
|
|
16, // max_b_frames
|
|
|
|
24, // gop_size
|
|
|
|
35, // crf
|
2019-12-12 12:13:10 +00:00
|
|
|
35, // qp
|
2019-12-06 19:52:08 +00:00
|
|
|
|
2019-12-06 20:41:30 +00:00
|
|
|
4, // threads
|
|
|
|
|
2019-12-06 19:52:08 +00:00
|
|
|
"baseline"s, // profile
|
|
|
|
"superfast"s, // preset
|
|
|
|
"zerolatency"s // tune
|
2019-12-03 19:23:33 +00:00
|
|
|
};
|
|
|
|
|
2020-01-17 23:58:27 +00:00
|
|
|
audio_t audio {};
|
|
|
|
|
2019-12-03 19:23:33 +00:00
|
|
|
stream_t stream {
|
2019-12-11 22:37:20 +00:00
|
|
|
2s, // ping_timeout
|
2019-12-16 21:02:21 +00:00
|
|
|
|
|
|
|
APPS_JSON,
|
|
|
|
|
2019-12-11 22:37:20 +00:00
|
|
|
13 // fecPercentage
|
2019-12-03 19:23:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
nvhttp_t nvhttp {
|
2019-12-27 15:04:18 +00:00
|
|
|
"lan", // origin_pin
|
2019-12-03 19:23:33 +00:00
|
|
|
PRIVATE_KEY_FILE,
|
|
|
|
CERTIFICATE_FILE,
|
|
|
|
|
2020-01-18 04:03:50 +00:00
|
|
|
boost::asio::ip::host_name(), // sunshine_name,
|
2019-12-27 15:04:18 +00:00
|
|
|
"03904e64-51da-4fb3-9afd-a9f7ff70fea4"s, // unique_id
|
|
|
|
"devices.json"s // file_devices
|
2019-12-03 19:23:33 +00:00
|
|
|
};
|
2019-12-03 22:19:00 +00:00
|
|
|
|
2019-12-22 22:34:12 +00:00
|
|
|
input_t input {
|
|
|
|
2s
|
|
|
|
};
|
|
|
|
|
2020-01-09 21:02:01 +00:00
|
|
|
sunshine_t sunshine {
|
|
|
|
2 // min_log_level
|
|
|
|
};
|
|
|
|
|
2019-12-03 22:19:00 +00:00
|
|
|
bool whitespace(char ch) {
|
|
|
|
return ch == ' ' || ch == '\t';
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string to_string(const char *begin, const char *end) {
|
|
|
|
return { begin, (std::size_t)(end - begin) };
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, std::string>> parse_line(std::string_view::const_iterator begin, std::string_view::const_iterator end) {
|
|
|
|
begin = std::find_if(begin, end, std::not_fn(whitespace));
|
|
|
|
end = std::find(begin, end, '#');
|
|
|
|
end = std::find_if(std::make_reverse_iterator(end), std::make_reverse_iterator(begin), std::not_fn(whitespace)).base();
|
|
|
|
|
|
|
|
auto eq = std::find(begin, end, '=');
|
|
|
|
if(eq == end || eq == begin) {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto end_name = std::find_if(std::make_reverse_iterator(eq - 1), std::make_reverse_iterator(begin), std::not_fn(whitespace)).base();
|
|
|
|
auto begin_val = std::find_if(eq + 1, end, std::not_fn(whitespace));
|
|
|
|
|
|
|
|
return std::pair { to_string(begin, end_name), to_string(begin_val, end) };
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unordered_map<std::string, std::string> parse_config(std::string_view file_content) {
|
|
|
|
std::unordered_map<std::string, std::string> vars;
|
|
|
|
|
2020-01-11 00:17:57 +00:00
|
|
|
auto pos = std::begin(file_content);
|
2019-12-03 22:19:00 +00:00
|
|
|
auto end = std::end(file_content);
|
|
|
|
|
2020-01-11 00:17:57 +00:00
|
|
|
while(pos < end) {
|
|
|
|
auto newline = std::find_if(pos, end, [](auto ch) { return ch == '\n' || ch == '\r'; });
|
|
|
|
auto var = parse_line(pos, newline);
|
2019-12-03 22:19:00 +00:00
|
|
|
|
2020-01-11 00:17:57 +00:00
|
|
|
pos = (*newline == '\r') ? newline + 2 : newline + 1;
|
2019-12-03 22:19:00 +00:00
|
|
|
if(!var) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
vars.emplace(std::move(*var));
|
|
|
|
}
|
|
|
|
|
|
|
|
return vars;
|
|
|
|
}
|
|
|
|
|
|
|
|
void string_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input) {
|
|
|
|
auto it = vars.find(name);
|
|
|
|
if(it == std::end(vars)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
input = std::move(it->second);
|
|
|
|
}
|
|
|
|
|
2019-12-27 15:04:18 +00:00
|
|
|
void string_restricted_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input, const std::vector<std::string_view> &allowed_vals) {
|
|
|
|
std::string temp;
|
|
|
|
string_f(vars, name, temp);
|
|
|
|
|
|
|
|
for(auto &allowed_val : allowed_vals) {
|
|
|
|
if(temp == allowed_val) {
|
|
|
|
input = std::move(temp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void int_restricted_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input, const std::vector<std::string_view> &allowed_vals) {
|
|
|
|
std::string temp;
|
|
|
|
string_f(vars, name, temp);
|
|
|
|
|
|
|
|
for(int x = 0; x < allowed_vals.size(); ++x) {
|
|
|
|
auto &allowed_val = allowed_vals[x];
|
|
|
|
|
|
|
|
if(temp == allowed_val) {
|
|
|
|
input = x;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 22:19:00 +00:00
|
|
|
void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input) {
|
|
|
|
auto it = vars.find(name);
|
|
|
|
|
|
|
|
if(it == std::end(vars)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto &val = it->second;
|
|
|
|
input = util::from_chars(&val[0], &val[0] + val.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
void parse_file(const char *file) {
|
|
|
|
std::ifstream in(file);
|
|
|
|
|
|
|
|
auto vars = parse_config(std::string {
|
|
|
|
// Quick and dirty
|
|
|
|
std::istreambuf_iterator<char>(in),
|
|
|
|
std::istreambuf_iterator<char>()
|
|
|
|
});
|
|
|
|
|
|
|
|
for(auto &[name, val] : vars) {
|
2020-01-09 21:02:01 +00:00
|
|
|
std::cout << "["sv << name << "] -- ["sv << val << ']' << std::endl;
|
2019-12-03 22:19:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int_f(vars, "max_b_frames", video.max_b_frames);
|
|
|
|
int_f(vars, "gop_size", video.gop_size);
|
|
|
|
int_f(vars, "crf", video.crf);
|
2019-12-12 12:13:10 +00:00
|
|
|
int_f(vars, "qp", video.qp);
|
2019-12-06 20:41:30 +00:00
|
|
|
int_f(vars, "threads", video.threads);
|
2019-12-06 19:52:08 +00:00
|
|
|
string_f(vars, "profile", video.profile);
|
|
|
|
string_f(vars, "preset", video.preset);
|
|
|
|
string_f(vars, "tune", video.tune);
|
2019-12-03 22:19:00 +00:00
|
|
|
|
|
|
|
string_f(vars, "pkey", nvhttp.pkey);
|
|
|
|
string_f(vars, "cert", nvhttp.cert);
|
2019-12-25 23:01:06 +00:00
|
|
|
string_f(vars, "sunshine_name", nvhttp.sunshine_name);
|
2019-12-03 22:19:00 +00:00
|
|
|
string_f(vars, "unique_id", nvhttp.unique_id);
|
|
|
|
string_f(vars, "file_devices", nvhttp.file_devices);
|
|
|
|
string_f(vars, "external_ip", nvhttp.external_ip);
|
|
|
|
|
2020-01-17 23:58:27 +00:00
|
|
|
string_f(vars, "audio_sink", audio.sink);
|
|
|
|
|
2019-12-27 15:04:18 +00:00
|
|
|
string_restricted_f(vars, "origin_pin_allowed", nvhttp.origin_pin_allowed, {
|
|
|
|
"pc"sv, "lan"sv, "wan"sv
|
|
|
|
});
|
|
|
|
|
2019-12-03 22:19:00 +00:00
|
|
|
int to = -1;
|
|
|
|
int_f(vars, "ping_timeout", to);
|
|
|
|
if(to > 0) {
|
|
|
|
stream.ping_timeout = std::chrono::milliseconds(to);
|
|
|
|
}
|
2019-12-16 21:02:21 +00:00
|
|
|
string_f(vars, "file_apps", stream.file_apps);
|
2019-12-11 22:37:20 +00:00
|
|
|
int_f(vars, "fec_percentage", stream.fec_percentage);
|
2019-12-22 22:34:12 +00:00
|
|
|
|
|
|
|
to = std::numeric_limits<int>::min();
|
|
|
|
int_f(vars, "back_button_timeout", to);
|
|
|
|
|
|
|
|
if(to > std::numeric_limits<int>::min()) {
|
|
|
|
input.back_button_timeout = std::chrono::milliseconds {to };
|
|
|
|
}
|
2020-01-09 21:02:01 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
});
|
|
|
|
|
2020-01-11 00:23:49 +00:00
|
|
|
if(!log_level_string.empty()) {
|
2020-01-09 21:02:01 +00:00
|
|
|
if(log_level_string == "verbose"sv) {
|
|
|
|
sunshine.min_log_level = 0;
|
|
|
|
}
|
|
|
|
else if(log_level_string == "debug"sv) {
|
|
|
|
sunshine.min_log_level = 1;
|
|
|
|
}
|
|
|
|
else if(log_level_string == "info"sv) {
|
|
|
|
sunshine.min_log_level = 2;
|
|
|
|
}
|
|
|
|
else if(log_level_string == "warning"sv) {
|
|
|
|
sunshine.min_log_level = 3;
|
|
|
|
}
|
|
|
|
else if(log_level_string == "error"sv) {
|
|
|
|
sunshine.min_log_level = 4;
|
|
|
|
}
|
|
|
|
else if(log_level_string == "fatal"sv) {
|
|
|
|
sunshine.min_log_level = 5;
|
|
|
|
}
|
|
|
|
else if(log_level_string == "none"sv) {
|
|
|
|
sunshine.min_log_level = 6;
|
|
|
|
}
|
|
|
|
}
|
2019-12-03 22:19:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-03 19:23:33 +00:00
|
|
|
}
|