mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-01-30 12:32:43 +00:00
Execute commands defined in apps.json
This commit is contained in:
parent
20f5f90588
commit
b7eab0883c
@ -1,29 +1,34 @@
|
|||||||
{
|
{
|
||||||
"env":[
|
"env":[
|
||||||
{ "VAR":"VAL", "VAR2":"VAL2" }
|
{
|
||||||
|
"DISPLAY":":0",
|
||||||
|
"DRI_PRIME":"1",
|
||||||
|
"XAUTHORITY":"/home/loki/.Xauthority"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"apps":[
|
"apps":[
|
||||||
{
|
{
|
||||||
"name":"echo-1",
|
"name":"Low Res Desktop 2",
|
||||||
|
"cmd":"sh -c \"while true; do sleep 10000; done;\"",
|
||||||
"output":"output.txt",
|
|
||||||
"cmd":"sh -c \"echo $VAR\"",
|
|
||||||
"prep-cmd":[
|
"prep-cmd":[
|
||||||
{ "do":"echo pre-1", "undo":"echo post-1" },
|
{ "do":"xrandr --output HDMI-1 --mode 1920x1080", "undo":"xrandr --output HDMI-1 --mode 1920x1200" }
|
||||||
{ "do":"echo pre-2" },
|
|
||||||
{ "do":"echo pre-3", "undo":"echo post-3" }
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"echo-2",
|
"name":"Low Res Desktop",
|
||||||
|
"cmd":"sh -c \"while true; do sleep 10000; done;\"",
|
||||||
"output":"output.txt",
|
|
||||||
"cmd":"sleep 10",
|
|
||||||
"prep-cmd":[
|
"prep-cmd":[
|
||||||
{ "do":"echo pre-1", "undo":"echo post-1" },
|
{ "do":"xrandr --output HDMI-1 --mode 1920x1080", "undo":"xrandr --output HDMI-1 --mode 1920x1200" }
|
||||||
{ "do":"echo pre-2" },
|
|
||||||
{ "do":"echo pre-3", "undo":"echo post-3" }
|
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Steam BigPicture",
|
||||||
|
|
||||||
|
"output":"steam.txt",
|
||||||
|
"cmd":"steam -bigpicture",
|
||||||
|
"prep-cmd":[
|
||||||
|
{ "do":"sh -c \"PATH=$PATH:$HOME/.local/bin sudo freeHugePages\""},
|
||||||
|
{ "do":"sh -c \"PATH=$PATH:$HOME/.local/bin sudo claim_amdgpu\"" }]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <boost/property_tree/ptree.hpp>
|
|
||||||
#include <boost/property_tree/json_parser.hpp>
|
|
||||||
|
|
||||||
#include "nvhttp.h"
|
#include "nvhttp.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -18,85 +15,9 @@ extern "C" {
|
|||||||
#include <rs.h>
|
#include <rs.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
namespace pt = boost::property_tree;
|
|
||||||
|
|
||||||
std::optional<proc::proc_t> parse(const std::string& file_name) {
|
|
||||||
pt::ptree tree;
|
|
||||||
|
|
||||||
try {
|
|
||||||
pt::read_json(file_name, tree);
|
|
||||||
|
|
||||||
auto &apps_node = tree.get_child("apps"s);
|
|
||||||
auto &env_vars = tree.get_child("env"s);
|
|
||||||
|
|
||||||
boost::process::environment env = boost::this_process::environment();
|
|
||||||
|
|
||||||
std::unordered_map<std::string, proc::ctx_t> apps;
|
|
||||||
for(auto &[_,app_node] : apps_node) {
|
|
||||||
proc::ctx_t ctx;
|
|
||||||
|
|
||||||
auto &prep_nodes = app_node.get_child("prep-cmd"s);
|
|
||||||
auto name = app_node.get<std::string>("name"s);
|
|
||||||
auto output = app_node.get_optional<std::string>("output"s);
|
|
||||||
auto cmd = app_node.get<std::string>("cmd"s);
|
|
||||||
|
|
||||||
std::vector<proc::cmd_t> prep_cmds;
|
|
||||||
prep_cmds.reserve(prep_nodes.size());
|
|
||||||
for(auto &[_, prep_node] : prep_nodes) {
|
|
||||||
auto do_cmd = prep_node.get<std::string>("do"s);
|
|
||||||
auto undo_cmd = prep_node.get_optional<std::string>("undo"s);
|
|
||||||
|
|
||||||
if(undo_cmd) {
|
|
||||||
prep_cmds.emplace_back(std::move(do_cmd), std::move(*undo_cmd));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
prep_cmds.emplace_back(std::move(do_cmd));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(output) {
|
|
||||||
ctx.output = std::move(*output);
|
|
||||||
}
|
|
||||||
ctx.cmd = std::move(cmd);
|
|
||||||
ctx.prep_cmds = std::move(prep_cmds);
|
|
||||||
|
|
||||||
apps.emplace(std::move(name), std::move(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto &[_,env_var] : env_vars) {
|
|
||||||
for(auto &[name,val] : env_var) {
|
|
||||||
env[name] = val.get_value<std::string>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return proc::proc_t {
|
|
||||||
std::move(env), std::move(apps)
|
|
||||||
};
|
|
||||||
} catch (std::exception &e) {
|
|
||||||
std::cout << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
auto proc_opt = parse(SUNSHINE_ASSETS_DIR "/apps.json");
|
|
||||||
|
|
||||||
if(!proc_opt) {
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &proc = *proc_opt;
|
|
||||||
|
|
||||||
proc.execute("echo-2");
|
|
||||||
std::this_thread::sleep_for(50ms);
|
|
||||||
|
|
||||||
proc.execute("echo-1");
|
|
||||||
std::this_thread::sleep_for(50ms);
|
|
||||||
return proc.running();
|
|
||||||
|
|
||||||
if(argc > 1) {
|
if(argc > 1) {
|
||||||
if(!std::filesystem::exists(argv[1])) {
|
if(!std::filesystem::exists(argv[1])) {
|
||||||
std::cout << "Error: Couldn't find configuration file ["sv << argv[1] << ']' << std::endl;
|
std::cout << "Error: Couldn't find configuration file ["sv << argv[1] << ']' << std::endl;
|
||||||
@ -106,6 +27,12 @@ int main(int argc, char *argv[]) {
|
|||||||
config::parse_file(argv[1]);
|
config::parse_file(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto proc_opt = proc::parse(SUNSHINE_ASSETS_DIR "/apps.json");
|
||||||
|
if(!proc_opt) {
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
proc::proc = std::move(*proc_opt);
|
||||||
|
|
||||||
reed_solomon_init();
|
reed_solomon_init();
|
||||||
|
|
||||||
std::thread httpThread { nvhttp::start };
|
std::thread httpThread { nvhttp::start };
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "nvhttp.h"
|
#include "nvhttp.h"
|
||||||
#include "platform/common.h"
|
#include "platform/common.h"
|
||||||
|
#include "process.h"
|
||||||
|
|
||||||
|
|
||||||
namespace nvhttp {
|
namespace nvhttp {
|
||||||
@ -441,20 +442,26 @@ void applist(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> respon
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto &apps = tree.add_child("root", pt::ptree {});
|
auto &apps = tree.add_child("root", pt::ptree {});
|
||||||
|
|
||||||
pt::ptree desktop;
|
pt::ptree desktop;
|
||||||
pt::ptree fakegame;
|
|
||||||
|
|
||||||
apps.put("<xmlattr>.status_code", 200);
|
apps.put("<xmlattr>.status_code", 200);
|
||||||
desktop.put("IsHdrSupported"s, 0);
|
desktop.put("IsHdrSupported"s, 0);
|
||||||
desktop.put("AppTitle"s, "Desktop");
|
desktop.put("AppTitle"s, "Desktop");
|
||||||
desktop.put("ID"s, 1);
|
desktop.put("ID"s, 1);
|
||||||
|
|
||||||
fakegame.put("IsHdrSupported"s, 0);
|
int x = 2;
|
||||||
fakegame.put("AppTitle"s, "FakeGame");
|
for(auto &[name, proc] : proc::proc.get_apps()) {
|
||||||
fakegame.put("ID"s, 2);
|
pt::ptree app;
|
||||||
|
|
||||||
|
app.put("IsHdrSupported"s, 0);
|
||||||
|
app.put("AppTitle"s, name);
|
||||||
|
app.put("ID"s, x++);
|
||||||
|
|
||||||
|
apps.push_back(std::make_pair("App", std::move(app)));
|
||||||
|
}
|
||||||
|
|
||||||
apps.push_back(std::make_pair("App", desktop));
|
apps.push_back(std::make_pair("App", desktop));
|
||||||
apps.push_back(std::make_pair("App", fakegame));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -462,6 +469,17 @@ void launch(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> respons
|
|||||||
print_req<T>(request);
|
print_req<T>(request);
|
||||||
|
|
||||||
auto args = request->parse_query_string();
|
auto args = request->parse_query_string();
|
||||||
|
|
||||||
|
auto appid = util::from_view(args.at("appid")) -2;
|
||||||
|
|
||||||
|
stream::app_name.clear();
|
||||||
|
if(appid >= 0) {
|
||||||
|
auto pos = std::begin(proc::proc.get_apps());
|
||||||
|
std::advance(pos, appid);
|
||||||
|
|
||||||
|
stream::app_name = pos->first;
|
||||||
|
}
|
||||||
|
|
||||||
auto clientID = args.at("uniqueid"s);
|
auto clientID = args.at("uniqueid"s);
|
||||||
auto aesKey = *util::from_hex<crypto::aes_t>(args.at("rikey"s), true);
|
auto aesKey = *util::from_hex<crypto::aes_t>(args.at("rikey"s), true);
|
||||||
uint32_t prepend_iv = util::endian::big<uint32_t>(util::from_view(args.at("rikeyid"s)));
|
uint32_t prepend_iv = util::endian::big<uint32_t>(util::from_view(args.at("rikeyid"s)));
|
||||||
|
@ -34,7 +34,7 @@ struct gamepad_state_t {
|
|||||||
|
|
||||||
std::string get_local_ip();
|
std::string get_local_ip();
|
||||||
|
|
||||||
void interrupt_process(std::uint64_t handle);
|
void terminate_process(std::uint64_t handle);
|
||||||
|
|
||||||
mic_t microphone();
|
mic_t microphone();
|
||||||
audio_t audio(mic_t &mic, std::uint32_t sample_size);
|
audio_t audio(mic_t &mic, std::uint32_t sample_size);
|
||||||
|
@ -84,8 +84,8 @@ std::string get_local_ip(int family) {
|
|||||||
|
|
||||||
std::string get_local_ip() { return get_local_ip(AF_INET); }
|
std::string get_local_ip() { return get_local_ip(AF_INET); }
|
||||||
|
|
||||||
void interrupt_process(std::uint64_t handle) {
|
void terminate_process(std::uint64_t handle) {
|
||||||
kill((pid_t)handle, SIGINT);
|
kill((pid_t)handle, SIGTERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct display_attr_t {
|
struct display_attr_t {
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
@ -14,6 +17,9 @@
|
|||||||
namespace proc {
|
namespace proc {
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
namespace bp = boost::process;
|
namespace bp = boost::process;
|
||||||
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
|
proc_t proc;
|
||||||
|
|
||||||
template<class Rep, class Period>
|
template<class Rep, class Period>
|
||||||
void process_end(bp::child &proc, const std::chrono::duration<Rep, Period>& rel_time) {
|
void process_end(bp::child &proc, const std::chrono::duration<Rep, Period>& rel_time) {
|
||||||
@ -21,10 +27,12 @@ void process_end(bp::child &proc, const std::chrono::duration<Rep, Period>& rel_
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
platf::interrupt_process((std::uint64_t)proc.native_handle());
|
std::cout << "Interruping Child-Process"sv << std::endl;
|
||||||
|
platf::terminate_process((std::uint64_t) proc.native_handle());
|
||||||
|
|
||||||
// Force termination if it takes too long
|
// Force termination if it takes too long
|
||||||
if(!proc.wait_for(rel_time)) {
|
if(!proc.wait_for(rel_time)) {
|
||||||
|
std::cout << "Force termination Child-Process"sv << std::endl;
|
||||||
proc.terminate();
|
proc.terminate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,8 +48,10 @@ int exe(const std::string &cmd, bp::environment &env, file_t &file, std::error_c
|
|||||||
int proc_t::execute(const std::string &name) {
|
int proc_t::execute(const std::string &name) {
|
||||||
auto it = _name_to_proc.find(name);
|
auto it = _name_to_proc.find(name);
|
||||||
|
|
||||||
|
std::cout << "Ensure clean slate"sv << std::endl;
|
||||||
// Ensure starting from a clean slate
|
// Ensure starting from a clean slate
|
||||||
_undo_pre_cmd();
|
_undo_pre_cmd();
|
||||||
|
std::cout << "Clean slate"sv << std::endl;
|
||||||
|
|
||||||
if(it == std::end(_name_to_proc)) {
|
if(it == std::end(_name_to_proc)) {
|
||||||
std::cout << "Error: Couldn't find ["sv << name << ']' << std::endl;
|
std::cout << "Error: Couldn't find ["sv << name << ']' << std::endl;
|
||||||
@ -137,7 +147,79 @@ void proc_t::_undo_pre_cmd() {
|
|||||||
|
|
||||||
_pipe.reset();
|
_pipe.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, ctx_t> &proc_t::get_apps() const {
|
||||||
|
return _name_to_proc;
|
||||||
|
}
|
||||||
|
|
||||||
proc_t::~proc_t() {
|
proc_t::~proc_t() {
|
||||||
_undo_pre_cmd();
|
_undo_pre_cmd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<proc::proc_t> parse(const std::string& file_name) {
|
||||||
|
pt::ptree tree;
|
||||||
|
|
||||||
|
try {
|
||||||
|
pt::read_json(file_name, tree);
|
||||||
|
|
||||||
|
auto &apps_node = tree.get_child("apps"s);
|
||||||
|
auto &env_vars = tree.get_child("env"s);
|
||||||
|
|
||||||
|
boost::process::environment env = boost::this_process::environment();
|
||||||
|
|
||||||
|
std::unordered_map<std::string, proc::ctx_t> apps;
|
||||||
|
for(auto &[_,app_node] : apps_node) {
|
||||||
|
proc::ctx_t ctx;
|
||||||
|
|
||||||
|
auto &prep_nodes = app_node.get_child("prep-cmd"s);
|
||||||
|
auto name = app_node.get<std::string>("name"s);
|
||||||
|
auto output = app_node.get_optional<std::string>("output"s);
|
||||||
|
auto cmd = app_node.get<std::string>("cmd"s);
|
||||||
|
|
||||||
|
std::vector<proc::cmd_t> prep_cmds;
|
||||||
|
prep_cmds.reserve(prep_nodes.size());
|
||||||
|
for(auto &[_, prep_node] : prep_nodes) {
|
||||||
|
auto do_cmd = prep_node.get<std::string>("do"s);
|
||||||
|
auto undo_cmd = prep_node.get_optional<std::string>("undo"s);
|
||||||
|
|
||||||
|
if(undo_cmd) {
|
||||||
|
prep_cmds.emplace_back(std::move(do_cmd), std::move(*undo_cmd));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prep_cmds.emplace_back(std::move(do_cmd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(output) {
|
||||||
|
ctx.output = std::move(*output);
|
||||||
|
}
|
||||||
|
ctx.cmd = std::move(cmd);
|
||||||
|
ctx.prep_cmds = std::move(prep_cmds);
|
||||||
|
|
||||||
|
apps.emplace(std::move(name), std::move(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto &[_,env_var] : env_vars) {
|
||||||
|
for(auto &[name,val] : env_var) {
|
||||||
|
env[name] = val.get_value<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return proc::proc_t {
|
||||||
|
std::move(env), std::move(apps)
|
||||||
|
};
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
std::cout << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh(const std::string &file_name) {
|
||||||
|
auto proc_opt = proc::parse(file_name);
|
||||||
|
|
||||||
|
if(proc_opt) {
|
||||||
|
proc = std::move(*proc_opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -6,8 +6,10 @@
|
|||||||
#define SUNSHINE_PROCESS_H
|
#define SUNSHINE_PROCESS_H
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include <boost/process.hpp>
|
#include <boost/process.hpp>
|
||||||
|
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
namespace proc {
|
namespace proc {
|
||||||
@ -41,7 +43,7 @@ struct ctx_t {
|
|||||||
|
|
||||||
class proc_t {
|
class proc_t {
|
||||||
public:
|
public:
|
||||||
KITTY_DEFAULT_CONSTR(proc_t)
|
KITTY_DEFAULT_CONSTR_THROW(proc_t)
|
||||||
|
|
||||||
proc_t(
|
proc_t(
|
||||||
boost::process::environment &&env,
|
boost::process::environment &&env,
|
||||||
@ -54,6 +56,7 @@ public:
|
|||||||
|
|
||||||
~proc_t();
|
~proc_t();
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, ctx_t> &get_apps() const;
|
||||||
private:
|
private:
|
||||||
void _undo_pre_cmd();
|
void _undo_pre_cmd();
|
||||||
|
|
||||||
@ -66,5 +69,9 @@ private:
|
|||||||
std::vector<cmd_t>::const_iterator _undo_begin;
|
std::vector<cmd_t>::const_iterator _undo_begin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void refresh(const std::string &file_name);
|
||||||
|
std::optional<proc::proc_t> parse(const std::string& file_name);
|
||||||
|
|
||||||
|
extern proc_t proc;
|
||||||
}
|
}
|
||||||
#endif //SUNSHINE_PROCESS_H
|
#endif //SUNSHINE_PROCESS_H
|
||||||
|
@ -31,6 +31,7 @@ extern "C" {
|
|||||||
#include "thread_safe.h"
|
#include "thread_safe.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
#include "process.h"
|
||||||
|
|
||||||
#define IDX_START_A 0
|
#define IDX_START_A 0
|
||||||
#define IDX_REQUEST_IDR_FRAME 0
|
#define IDX_REQUEST_IDR_FRAME 0
|
||||||
@ -88,8 +89,10 @@ struct audio_packet_raw_t {
|
|||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
//TODO: Bundle in thread safe container
|
||||||
crypto::aes_t gcm_key;
|
crypto::aes_t gcm_key;
|
||||||
crypto::aes_t iv;
|
crypto::aes_t iv;
|
||||||
|
std::string app_name;
|
||||||
|
|
||||||
struct config_t {
|
struct config_t {
|
||||||
audio::config_t audio;
|
audio::config_t audio;
|
||||||
@ -114,6 +117,8 @@ struct session_t {
|
|||||||
|
|
||||||
crypto::aes_t gcm_key;
|
crypto::aes_t gcm_key;
|
||||||
crypto::aes_t iv;
|
crypto::aes_t iv;
|
||||||
|
|
||||||
|
std::string app_name;
|
||||||
} session;
|
} session;
|
||||||
|
|
||||||
void free_msg(PRTSP_MESSAGE msg) {
|
void free_msg(PRTSP_MESSAGE msg) {
|
||||||
@ -166,7 +171,7 @@ public:
|
|||||||
parseRtspMessage(req.get(), (char*)packet->data, packet->dataLength);
|
parseRtspMessage(req.get(), (char*)packet->data, packet->dataLength);
|
||||||
for(auto option = req->options; option != nullptr; option = option->next) {
|
for(auto option = req->options; option != nullptr; option = option->next) {
|
||||||
if("Content-length"sv == option->option) {
|
if("Content-length"sv == option->option) {
|
||||||
_queue_packet = std::make_pair(std::move(peer), std::move(packet));
|
_queue_packet = std::make_pair(peer, std::move(packet));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,6 +277,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void map(uint16_t type, std::function<void(const std::string_view&)> cb);
|
void map(uint16_t type, std::function<void(const std::string_view&)> cb);
|
||||||
|
void send(const std::string_view &payload);
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::uint16_t, std::function<void(const std::string_view&)>> _map_type_cb;
|
std::unordered_map<std::uint16_t, std::function<void(const std::string_view&)>> _map_type_cb;
|
||||||
ENetAddress _addr;
|
ENetAddress _addr;
|
||||||
@ -431,6 +437,17 @@ void control_server_t::map(uint16_t type, std::function<void(const std::string_v
|
|||||||
_map_type_cb.emplace(type, std::move(cb));
|
_map_type_cb.emplace(type, std::move(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void control_server_t::send(const std::string_view & payload) {
|
||||||
|
std::for_each(_host->peers, _host->peers + _host->peerCount, [payload](auto &peer) {
|
||||||
|
auto packet = enet_packet_create(payload.data(), payload.size(), ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
if(enet_peer_send(&peer, 0, packet)) {
|
||||||
|
enet_packet_destroy(packet);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
enet_host_flush(_host.get());
|
||||||
|
}
|
||||||
|
|
||||||
void controlThread(video::idr_event_t idr_events) {
|
void controlThread(video::idr_event_t idr_events) {
|
||||||
control_server_t server { CONTROL_PORT };
|
control_server_t server { CONTROL_PORT };
|
||||||
|
|
||||||
@ -515,6 +532,21 @@ void controlThread(video::idr_event_t idr_events) {
|
|||||||
session.audio_packets->stop();
|
session.audio_packets->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!session.app_name.empty() && !proc::proc.running()) {
|
||||||
|
std::cout << "Process terminated"sv << std::endl;
|
||||||
|
|
||||||
|
std::uint16_t reason = 0x0100;
|
||||||
|
|
||||||
|
std::array<std::uint16_t, 2> payload;
|
||||||
|
payload[0] = packetTypes[IDX_TERMINATION];
|
||||||
|
payload[1] = reason;
|
||||||
|
|
||||||
|
server.send(std::string_view {(char*)payload.data(), payload.size()});
|
||||||
|
|
||||||
|
session.video_packets->stop();
|
||||||
|
session.audio_packets->stop();
|
||||||
|
}
|
||||||
|
|
||||||
server.iterate(500ms);
|
server.iterate(500ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -885,6 +917,22 @@ void cmd_announce(host_t &host, peer_t peer, msg_t &&req) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!app_name.empty() && session.app_name != app_name ) {
|
||||||
|
if(auto err_code = proc::proc.execute(app_name)) {
|
||||||
|
if(err_code == 404) {
|
||||||
|
respond(host, peer, &option, 404, (app_name + " NOT FOUND").c_str(), req->sequenceNumber, {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
respond(host, peer, &option, 500, "INTERNAL ERROR", req->sequenceNumber, {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
session.app_name = std::move(app_name);
|
||||||
|
|
||||||
std::copy(std::begin(gcm_key), std::end(gcm_key), std::begin(session.gcm_key));
|
std::copy(std::begin(gcm_key), std::end(gcm_key), std::begin(session.gcm_key));
|
||||||
std::copy(std::begin(iv), std::end(iv), std::begin(session.iv));
|
std::copy(std::begin(iv), std::end(iv), std::begin(session.iv));
|
||||||
|
|
||||||
|
@ -9,8 +9,10 @@
|
|||||||
|
|
||||||
namespace stream {
|
namespace stream {
|
||||||
|
|
||||||
|
//FIXME: Make thread safe
|
||||||
extern crypto::aes_t gcm_key;
|
extern crypto::aes_t gcm_key;
|
||||||
extern crypto::aes_t iv;
|
extern crypto::aes_t iv;
|
||||||
|
extern std::string app_name;
|
||||||
|
|
||||||
void rtpThread();
|
void rtpThread();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user