mirror of
https://github.com/rock88/moonlight-nx
synced 2024-11-10 06:14:15 +00:00
Save/load settings with jansson
This commit is contained in:
parent
5bdcd23506
commit
147fe08426
12 changed files with 146 additions and 112 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -4,6 +4,3 @@
|
|||
[submodule "third_party/nanogui"]
|
||||
path = third_party/nanogui
|
||||
url=https://github.com/rock88/nanogui.git
|
||||
[submodule "third_party/json"]
|
||||
path = third_party/json
|
||||
url = https://github.com/nlohmann/json.git
|
||||
|
|
|
@ -65,8 +65,7 @@ M_INCLUDES := \
|
|||
-I$(TOPDIR)/third_party/moonlight-common-c/src \
|
||||
-I$(TOPDIR)/third_party/moonlight-common-c/enet/include \
|
||||
-I$(TOPDIR)/third_party/nanogui/include \
|
||||
-I$(TOPDIR)/third_party/nanogui/ext/nanovg/src \
|
||||
-I$(TOPDIR)/third_party/json/single_include/nlohmann
|
||||
-I$(TOPDIR)/third_party/nanogui/ext/nanovg/src
|
||||
|
||||
DEFINES := -DNANOGUI_USE_OPENGL -DNVG_STB_IMAGE_IMPLEMENTATION -DNANOGUI_NO_GLFW \
|
||||
-DHAS_SOCKLEN_T -DHAS_POLL -DHAS_FCNTL -D_GNU_SOURCE -DUSE_MBEDTLS_CRYPTO
|
||||
|
@ -84,7 +83,7 @@ LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*
|
|||
LIBS := -lcurl -lmbedtls -lmbedx509 -lmbedcrypto \
|
||||
-lavcodec -lavutil -lopus -lbz2 -lz -lexpat -lm \
|
||||
-lglad -lEGL -lglapi -ldrm_nouveau -lglfw3 \
|
||||
-lnx -lwebp -lswresample -lavformat -lvpx
|
||||
-lnx -lwebp -lswresample -lavformat -lvpx -ljansson
|
||||
|
||||
LIBGAMESTREAM_C_SOURCES = \
|
||||
xml.c
|
||||
|
|
|
@ -20,9 +20,7 @@
|
|||
#include "http.h"
|
||||
#include "client.h"
|
||||
#include "errors.h"
|
||||
#include "limits.h"
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -39,35 +37,6 @@
|
|||
static char* unique_id = "0123456789ABCDEF";
|
||||
const char* gs_error;
|
||||
|
||||
int mkdirtree(const char* directory) {
|
||||
char buffer[PATH_MAX];
|
||||
char* p = buffer;
|
||||
|
||||
// The passed in string could be a string literal
|
||||
// so we must copy it first
|
||||
strncpy(p, directory, PATH_MAX - 1);
|
||||
buffer[PATH_MAX - 1] = '\0';
|
||||
|
||||
while (*p != 0) {
|
||||
// Find the end of the path element
|
||||
do {
|
||||
p++;
|
||||
} while (*p != 0 && *p != '/');
|
||||
|
||||
char oldChar = *p;
|
||||
*p = 0;
|
||||
|
||||
// Create the directory if it doesn't exist already
|
||||
if (mkdir(buffer, 0775) == -1 && errno != EEXIST) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*p = oldChar;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_server_status(PSERVER_DATA server) {
|
||||
int ret;
|
||||
char url[4096];
|
||||
|
|
|
@ -44,7 +44,6 @@ typedef struct _SERVER_DATA {
|
|||
SERVER_INFORMATION serverInfo;
|
||||
} SERVER_DATA, *PSERVER_DATA;
|
||||
|
||||
int mkdirtree(const char* directory);
|
||||
int gs_init(PSERVER_DATA server, char* address, const char *keyDirectory, int logLevel, bool unsupported);
|
||||
int gs_app_boxart(PSERVER_DATA server, int app_id, char **art_data, size_t *art_data_size);
|
||||
int gs_start_app(PSERVER_DATA server, PSTREAM_CONFIGURATION config, int appId, bool sops, bool localaudio, int gamepad_mask);
|
||||
|
|
|
@ -1044,7 +1044,6 @@
|
|||
"\"$(SRCROOT)/src/nanogui_resources\"",
|
||||
"\"$(SRCROOT)/third_party/moonlight-common-c/enet/include\"",
|
||||
"\"$(SRCROOT)/third_party/moonlight-common-c/src\"",
|
||||
"\"$(SRCROOT)/third_party/json/single_include/nlohmann\"",
|
||||
"\"$(SRCROOT)/src/switch\"",
|
||||
/opt/devkitpro/libnx/include2,
|
||||
);
|
||||
|
@ -1078,6 +1077,7 @@
|
|||
"-lmbedtls",
|
||||
"-lmbedx509",
|
||||
"-lmbedcrypto",
|
||||
"-ljansson",
|
||||
);
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
|
@ -1134,7 +1134,6 @@
|
|||
"\"$(SRCROOT)/src/nanogui_resources\"",
|
||||
"\"$(SRCROOT)/third_party/moonlight-common-c/enet/include\"",
|
||||
"\"$(SRCROOT)/third_party/moonlight-common-c/src\"",
|
||||
"\"$(SRCROOT)/third_party/json/single_include/nlohmann\"",
|
||||
"\"$(SRCROOT)/src/switch\"",
|
||||
/opt/devkitpro/libnx/include2,
|
||||
);
|
||||
|
@ -1167,6 +1166,7 @@
|
|||
"-lmbedtls",
|
||||
"-lmbedx509",
|
||||
"-lmbedcrypto",
|
||||
"-ljansson",
|
||||
);
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
|
|
|
@ -79,8 +79,7 @@ void GameStreamClient::connect(const std::string &address, ServerCallback<SERVER
|
|||
|
||||
perform_async([this, address, callback] {
|
||||
// TODO: mem leak here :(
|
||||
std::string key_dir = Settings::settings()->working_dir() + "/key";
|
||||
int status = gs_init(&m_server_data[address], (char *)(new std::string(address))->c_str(), key_dir.c_str(), 0, false);
|
||||
int status = gs_init(&m_server_data[address], (char *)(new std::string(address))->c_str(), Settings::settings()->key_dir().c_str(), 0, false);
|
||||
|
||||
nanogui::async([this, address, callback, status] {
|
||||
if (status == GS_OK) {
|
||||
|
|
160
src/Settings.cpp
160
src/Settings.cpp
|
@ -1,14 +1,51 @@
|
|||
#include "Settings.hpp"
|
||||
#include "Log.h"
|
||||
#include "json.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <jansson.h>
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include <iomanip>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define JSON_GET_VALUE(to, json, check, type) \
|
||||
if (json.check()) { \
|
||||
to = json.get<type>(); \
|
||||
static int mkdirtree(const char* directory) {
|
||||
char buffer[PATH_MAX];
|
||||
char* p = buffer;
|
||||
|
||||
// The passed in string could be a string literal
|
||||
// so we must copy it first
|
||||
strncpy(p, directory, PATH_MAX - 1);
|
||||
buffer[PATH_MAX - 1] = '\0';
|
||||
|
||||
while (*p != 0) {
|
||||
// Find the end of the path element
|
||||
do {
|
||||
p++;
|
||||
} while (*p != 0 && *p != '/');
|
||||
|
||||
char oldChar = *p;
|
||||
*p = 0;
|
||||
|
||||
// Create the directory if it doesn't exist already
|
||||
if (mkdir(buffer, 0775) == -1 && errno != EEXIST) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*p = oldChar;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Settings::set_working_dir(std::string working_dir) {
|
||||
m_working_dir = working_dir;
|
||||
m_key_dir = working_dir + "/key";
|
||||
m_boxart_dir = working_dir + "/boxart";
|
||||
|
||||
mkdirtree(m_working_dir.c_str());
|
||||
mkdirtree(m_key_dir.c_str());
|
||||
mkdirtree(m_boxart_dir.c_str());
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
void Settings::add_host(const std::string address) {
|
||||
if (std::find(m_hosts.begin(), m_hosts.end(), address) == m_hosts.end()) {
|
||||
|
@ -18,48 +55,91 @@ void Settings::add_host(const std::string address) {
|
|||
}
|
||||
|
||||
void Settings::load() {
|
||||
try {
|
||||
std::ifstream stream(m_working_dir + "/settings.json");
|
||||
|
||||
if (!stream) {
|
||||
return;
|
||||
json_t* root = json_load_file((m_working_dir + "/settings.json").c_str(), 0, NULL);
|
||||
|
||||
if (root && json_typeof(root) == JSON_OBJECT) {
|
||||
if (json_t* hosts = json_object_get(root, "hosts")) {
|
||||
size_t size = json_array_size(hosts);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (json_t* host = json_array_get(hosts, i)) {
|
||||
if (json_typeof(host) == JSON_STRING) {
|
||||
m_hosts.push_back(json_string_value(host));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json json;
|
||||
stream >> json;
|
||||
if (json_t* settings = json_object_get(root, "settings")) {
|
||||
if (json_t* resolution = json_object_get(settings, "resolution")) {
|
||||
if (json_typeof(resolution) == JSON_INTEGER) {
|
||||
m_resolution = (int)json_integer_value(resolution);
|
||||
}
|
||||
}
|
||||
|
||||
if (json_t* fps = json_object_get(settings, "fps")) {
|
||||
if (json_typeof(fps) == JSON_INTEGER) {
|
||||
m_fps = (VideoCodec)json_integer_value(fps);
|
||||
}
|
||||
}
|
||||
|
||||
if (json_t* video_codec = json_object_get(settings, "video_codec")) {
|
||||
if (json_typeof(video_codec) == JSON_INTEGER) {
|
||||
m_video_codec = (VideoCodec)json_integer_value(video_codec);
|
||||
}
|
||||
}
|
||||
|
||||
if (json_t* bitrate = json_object_get(settings, "bitrate")) {
|
||||
if (json_typeof(bitrate) == JSON_INTEGER) {
|
||||
m_bitrate = (int)json_integer_value(bitrate);
|
||||
}
|
||||
}
|
||||
|
||||
if (json_t* swap_ab_xy = json_object_get(settings, "swap_ab_xy")) {
|
||||
if (json_typeof(swap_ab_xy) == JSON_TRUE) {
|
||||
m_swap_ab_xy = true;
|
||||
} else if (json_typeof(swap_ab_xy) == JSON_FALSE) {
|
||||
m_swap_ab_xy = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (json_t* decoder_threads = json_object_get(settings, "decoder_threads")) {
|
||||
if (json_typeof(decoder_threads) == JSON_INTEGER) {
|
||||
m_decoder_threads = (int)json_integer_value(decoder_threads);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSON_GET_VALUE(m_hosts, json["hosts"], is_array, std::vector<std::string>);
|
||||
JSON_GET_VALUE(m_resolution, json["settings"]["resolution"], is_number_integer, int);
|
||||
JSON_GET_VALUE(m_fps, json["settings"]["fps"], is_number_integer, int);
|
||||
JSON_GET_VALUE(m_video_codec, json["settings"]["video_codec"], is_number_integer, VideoCodec);
|
||||
JSON_GET_VALUE(m_bitrate, json["settings"]["bitrate"], is_number_integer, int);
|
||||
JSON_GET_VALUE(m_swap_ab_xy, json["settings"]["swap_ab_xy"], is_number_integer, bool);
|
||||
JSON_GET_VALUE(m_decoder_threads, json["settings"]["decoder_threads"], is_number_integer, int);
|
||||
|
||||
//stream.close();
|
||||
} catch (const std::exception &e) {
|
||||
LOG_FMT("Load settings error: %s\n", e.what());
|
||||
json_decref(root);
|
||||
}
|
||||
}
|
||||
|
||||
void Settings::save() {
|
||||
try {
|
||||
nlohmann::json json;
|
||||
json_t* root = json_object();
|
||||
|
||||
if (root) {
|
||||
if (json_t* hosts = json_array()) {
|
||||
for (auto host: m_hosts) {
|
||||
json_array_append(hosts, json_string(host.c_str()));
|
||||
}
|
||||
json_object_set(root, "hosts", hosts);
|
||||
}
|
||||
|
||||
json["hosts"] = m_hosts;
|
||||
json["settings"] = {
|
||||
{"resolution", m_resolution},
|
||||
{"fps", m_fps},
|
||||
{"video_codec", m_video_codec},
|
||||
{"bitrate", m_bitrate},
|
||||
{"swap_ab_xy", m_swap_ab_xy},
|
||||
{"decoder_threads", m_decoder_threads}
|
||||
};
|
||||
if (json_t* settings = json_object()) {
|
||||
json_object_set(root, "resolution", json_integer(m_resolution));
|
||||
json_object_set(root, "fps", json_integer(m_fps));
|
||||
json_object_set(root, "video_codec", json_integer(m_video_codec));
|
||||
json_object_set(root, "bitrate", json_integer(m_bitrate));
|
||||
json_object_set(root, "decoder_threads", json_integer(m_decoder_threads));
|
||||
|
||||
if (m_swap_ab_xy) {
|
||||
json_object_set(root, "swap_ab_xy", json_true());
|
||||
} else {
|
||||
json_object_set(root, "swap_ab_xy", json_false());
|
||||
}
|
||||
}
|
||||
|
||||
std::ofstream stream(m_working_dir + "/settings.json");
|
||||
stream << std::setw(4) << json << std::endl;
|
||||
//stream.close();
|
||||
} catch (const std::exception &e) {
|
||||
LOG_FMT("Save settings error: %s\n", e.what());
|
||||
json_dump_file(root, (m_working_dir + "/settings.json").c_str(), JSON_INDENT(4));
|
||||
|
||||
json_decref(root);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,14 @@ public:
|
|||
return &settings;
|
||||
}
|
||||
|
||||
std::string working_dir() const {
|
||||
return m_working_dir;
|
||||
void set_working_dir(std::string working_dir);
|
||||
|
||||
std::string key_dir() const {
|
||||
return m_key_dir;
|
||||
}
|
||||
|
||||
void set_working_dir(std::string working_dir) {
|
||||
m_working_dir = std::string(working_dir);
|
||||
load();
|
||||
std::string boxart_dir() const {
|
||||
return m_boxart_dir;
|
||||
}
|
||||
|
||||
std::vector<std::string> hosts() const {
|
||||
|
@ -87,6 +88,9 @@ private:
|
|||
Settings() {};
|
||||
|
||||
std::string m_working_dir;
|
||||
std::string m_key_dir;
|
||||
std::string m_boxart_dir;
|
||||
|
||||
std::vector<std::string> m_hosts;
|
||||
int m_resolution = 720;
|
||||
int m_fps = 30;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "MbedTLSCryptoManager.hpp"
|
||||
#include "Settings.hpp"
|
||||
#include "client.h"
|
||||
#include <string.h>
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
|
@ -18,9 +17,8 @@ static bool _generate_new_cert_key_pair();
|
|||
|
||||
bool MbedTLSCryptoManager::load_cert_key_pair() {
|
||||
if (m_key.is_empty() || m_cert.is_empty()) {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
Data cert = Data::read_from_file(key_dir + CERTIFICATE_FILE_NAME);
|
||||
Data key = Data::read_from_file(key_dir + KEY_FILE_NAME);
|
||||
Data cert = Data::read_from_file(Settings::settings()->key_dir() + "/" + CERTIFICATE_FILE_NAME);
|
||||
Data key = Data::read_from_file(Settings::settings()->key_dir() + "/" + KEY_FILE_NAME);
|
||||
|
||||
if (!cert.is_empty() && !key.is_empty()) {
|
||||
m_cert = cert;
|
||||
|
@ -35,10 +33,8 @@ bool MbedTLSCryptoManager::load_cert_key_pair() {
|
|||
bool MbedTLSCryptoManager::generate_new_cert_key_pair() {
|
||||
if (_generate_new_cert_key_pair()) {
|
||||
if (!m_cert.is_empty() && !m_key.is_empty()) {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
mkdirtree(key_dir.c_str());
|
||||
m_cert.write_to_file(key_dir + CERTIFICATE_FILE_NAME);
|
||||
m_key.write_to_file(key_dir + KEY_FILE_NAME);
|
||||
m_cert.write_to_file(Settings::settings()->key_dir() + "/" + CERTIFICATE_FILE_NAME);
|
||||
m_key.write_to_file(Settings::settings()->key_dir() + "/" + KEY_FILE_NAME);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -46,9 +42,8 @@ bool MbedTLSCryptoManager::generate_new_cert_key_pair() {
|
|||
}
|
||||
|
||||
void MbedTLSCryptoManager::remove_cert_key_pair() {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
remove((key_dir + CERTIFICATE_FILE_NAME).c_str());
|
||||
remove((key_dir + KEY_FILE_NAME).c_str());
|
||||
remove((Settings::settings()->key_dir() + "/" + CERTIFICATE_FILE_NAME).c_str());
|
||||
remove((Settings::settings()->key_dir() + "/" + KEY_FILE_NAME).c_str());
|
||||
m_cert = Data();
|
||||
m_key = Data();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "OpenSSLCryptoManager.hpp"
|
||||
#include "Settings.hpp"
|
||||
#include "client.h"
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
#include <openssl/aes.h>
|
||||
|
@ -22,9 +21,8 @@ static bool _generate_new_cert_key_pair();
|
|||
|
||||
bool OpenSSLCryptoManager::load_cert_key_pair() {
|
||||
if (m_key.is_empty() || m_cert.is_empty()) {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
Data cert = Data::read_from_file(key_dir + CERTIFICATE_FILE_NAME);
|
||||
Data key = Data::read_from_file(key_dir + KEY_FILE_NAME);
|
||||
Data cert = Data::read_from_file(Settings::settings()->key_dir() + "/" + CERTIFICATE_FILE_NAME);
|
||||
Data key = Data::read_from_file(Settings::settings()->key_dir() + "/" + KEY_FILE_NAME);
|
||||
|
||||
if (!cert.is_empty() && !key.is_empty()) {
|
||||
m_cert = cert;
|
||||
|
@ -39,10 +37,8 @@ bool OpenSSLCryptoManager::load_cert_key_pair() {
|
|||
bool OpenSSLCryptoManager::generate_new_cert_key_pair() {
|
||||
if (_generate_new_cert_key_pair()) {
|
||||
if (!m_cert.is_empty() && !m_key.is_empty()) {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
mkdirtree(key_dir.c_str());
|
||||
m_cert.write_to_file(key_dir + CERTIFICATE_FILE_NAME);
|
||||
m_key.write_to_file(key_dir + KEY_FILE_NAME);
|
||||
m_cert.write_to_file(Settings::settings()->key_dir() + "/" + CERTIFICATE_FILE_NAME);
|
||||
m_key.write_to_file(Settings::settings()->key_dir() + "/" + KEY_FILE_NAME);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -50,9 +46,8 @@ bool OpenSSLCryptoManager::generate_new_cert_key_pair() {
|
|||
}
|
||||
|
||||
void OpenSSLCryptoManager::remove_cert_key_pair() {
|
||||
auto key_dir = Settings::settings()->working_dir() + "/key/";
|
||||
remove((key_dir + CERTIFICATE_FILE_NAME).c_str());
|
||||
remove((key_dir + KEY_FILE_NAME).c_str());
|
||||
remove((Settings::settings()->key_dir() + "/" + CERTIFICATE_FILE_NAME).c_str());
|
||||
remove((Settings::settings()->key_dir() + "/" + KEY_FILE_NAME).c_str());
|
||||
m_cert = Data();
|
||||
m_key = Data();
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "Application.hpp"
|
||||
#include "InputController.hpp"
|
||||
#include "Settings.hpp"
|
||||
#include "client.h"
|
||||
|
||||
struct retro_hw_render_callback hw_render;
|
||||
|
||||
|
@ -61,7 +60,6 @@ void moonlight_init(int width, int height) {
|
|||
|
||||
void retro_init(void) {
|
||||
#ifdef __LAKKA_SWITCH__
|
||||
mkdirtree("/storage/system/moonlight");
|
||||
Settings::settings()->set_working_dir("/storage/system/moonlight");
|
||||
#endif
|
||||
|
||||
|
|
1
third_party/json
vendored
1
third_party/json
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit a50a14088c5c131d57f6dd6f91741da49c1ce426
|
Loading…
Reference in a new issue