clang-format

This commit is contained in:
loki 2021-05-17 21:21:57 +02:00
commit 3d8a99f541
43 changed files with 1915 additions and 1870 deletions

67
.clang-format Normal file
View file

@ -0,0 +1,67 @@
# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: AcrossComments
AlignOperands: Align
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterUnion: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 2
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 2
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Right
ReflowComments: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: Never
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 2
Cpp11BracedListStyle: false
UseTab: Never

View file

@ -4,14 +4,14 @@
#include "platform/common.h"
#include "utility.h"
#include "thread_safe.h"
#include "audio.h"
#include "main.h"
#include "thread_safe.h"
#include "utility.h"
namespace audio {
using namespace std::literals;
using opus_t = util::safe_ptr<OpusMSEncoder, opus_multistream_encoder_destroy>;
using opus_t = util::safe_ptr<OpusMSEncoder, opus_multistream_encoder_destroy>;
using sample_queue_t = std::shared_ptr<safe::queue_t<std::vector<std::int16_t>>>;
struct opus_stream_config_t {
@ -23,31 +23,31 @@ struct opus_stream_config_t {
};
constexpr std::uint8_t map_stereo[] { 0, 1 };
constexpr std::uint8_t map_surround51[] {0, 4, 1, 5, 2, 3};
constexpr std::uint8_t map_high_surround51[] {0, 1, 2, 3, 4, 5};
constexpr auto SAMPLE_RATE = 48000;
constexpr std::uint8_t map_surround51[] { 0, 4, 1, 5, 2, 3 };
constexpr std::uint8_t map_high_surround51[] { 0, 1, 2, 3, 4, 5 };
constexpr auto SAMPLE_RATE = 48000;
static opus_stream_config_t stereo = {
SAMPLE_RATE,
2,
1,
1,
map_stereo
SAMPLE_RATE,
2,
1,
1,
map_stereo
};
static opus_stream_config_t Surround51 = {
SAMPLE_RATE,
6,
4,
2,
map_surround51
SAMPLE_RATE,
6,
4,
2,
map_surround51
};
static opus_stream_config_t HighSurround51 = {
SAMPLE_RATE,
6,
6,
0,
map_high_surround51
SAMPLE_RATE,
6,
6,
0,
map_high_surround51
};
void encodeThread(packet_queue_t packets, sample_queue_t samples, config_t config, void *channel_data) {
@ -60,12 +60,11 @@ void encodeThread(packet_queue_t packets, sample_queue_t samples, config_t confi
stream->coupledStreams,
stream->mapping,
OPUS_APPLICATION_AUDIO,
nullptr)
};
nullptr) };
auto frame_size = config.packetDuration * stream->sampleRate / 1000;
while(auto sample = samples->pop()) {
packet_t packet { 16*1024 }; // 16KB
packet_t packet { 16 * 1024 }; // 16KB
int bytes = opus_multistream_encode(opus.get(), sample->data(), frame_size, std::begin(packet), packet.size());
if(bytes < 0) {
@ -94,12 +93,12 @@ void capture(safe::signal_t *shutdown_event, packet_queue_t packets, config_t co
//FIXME: Pick correct opus_stream_config_t based on config.channels
auto stream = &stereo;
auto frame_size = config.packetDuration * stream->sampleRate / 1000;
auto frame_size = config.packetDuration * stream->sampleRate / 1000;
int samples_per_frame = frame_size * stream->channelCount;
auto mic = platf::microphone(stream->sampleRate, frame_size);
if(!mic) {
BOOST_LOG(error) << "Couldn't create audio input"sv ;
BOOST_LOG(error) << "Couldn't create audio input"sv;
return;
}
@ -110,24 +109,24 @@ void capture(safe::signal_t *shutdown_event, packet_queue_t packets, config_t co
auto status = mic->sample(sample_buffer);
switch(status) {
case platf::capture_e::ok:
break;
case platf::capture_e::timeout:
continue;
case platf::capture_e::reinit:
mic.reset();
mic = platf::microphone(stream->sampleRate, frame_size);
if(!mic) {
BOOST_LOG(error) << "Couldn't re-initialize audio input"sv ;
case platf::capture_e::ok:
break;
case platf::capture_e::timeout:
continue;
case platf::capture_e::reinit:
mic.reset();
mic = platf::microphone(stream->sampleRate, frame_size);
if(!mic) {
BOOST_LOG(error) << "Couldn't re-initialize audio input"sv;
return;
}
return;
default:
return;
}
return;
default:
return;
}
samples->raise(std::move(sample_buffer));
}
}
}
} // namespace audio

View file

@ -1,8 +1,8 @@
#ifndef SUNSHINE_AUDIO_H
#define SUNSHINE_AUDIO_H
#include "utility.h"
#include "thread_safe.h"
#include "utility.h"
namespace audio {
struct config_t {
int packetDuration;
@ -10,9 +10,9 @@ struct config_t {
int mask;
};
using packet_t = util::buffer_t<std::uint8_t>;
using packet_queue_t = std::shared_ptr<safe::queue_t<std::pair<void*, packet_t>>>;
using packet_t = util::buffer_t<std::uint8_t>;
using packet_queue_t = std::shared_ptr<safe::queue_t<std::pair<void *, packet_t>>>;
void capture(safe::signal_t *shutdown_event, packet_queue_t packets, config_t config, void *channel_data);
}
} // namespace audio
#endif

View file

@ -1,12 +1,12 @@
#include <fstream>
#include <iostream>
#include <functional>
#include <iostream>
#include <unordered_map>
#include <boost/asio.hpp>
#include "utility.h"
#include "config.h"
#include "utility.h"
#define CA_DIR "credentials"
#define PRIVATE_KEY_FILE CA_DIR "/cakey.pem"
@ -33,12 +33,12 @@ enum preset_e : int {
};
enum rc_e : int {
constqp = 0x0, /**< Constant QP mode */
vbr = 0x1, /**< Variable bitrate mode */
cbr = 0x2, /**< Constant bitrate mode */
cbr_ld_hq = 0x8, /**< low-delay CBR, high quality */
cbr_hq = 0x10, /**< CBR, high quality (slower) */
vbr_hq = 0x20 /**< VBR, high quality (slower) */
constqp = 0x0, /**< Constant QP mode */
vbr = 0x1, /**< Variable bitrate mode */
cbr = 0x2, /**< Constant bitrate mode */
cbr_ld_hq = 0x8, /**< low-delay CBR, high quality */
cbr_hq = 0x10, /**< CBR, high quality (slower) */
vbr_hq = 0x20 /**< VBR, high quality (slower) */
};
enum coder_e : int {
@ -48,7 +48,8 @@ enum coder_e : int {
};
std::optional<preset_e> preset_from_view(const std::string_view &preset) {
#define _CONVERT_(x) if(preset == #x##sv) return x
#define _CONVERT_(x) \
if(preset == #x##sv) return x
_CONVERT_(slow);
_CONVERT_(medium);
_CONVERT_(fast);
@ -65,7 +66,8 @@ std::optional<preset_e> preset_from_view(const std::string_view &preset) {
}
std::optional<rc_e> rc_from_view(const std::string_view &rc) {
#define _CONVERT_(x) if(rc == #x##sv) return x
#define _CONVERT_(x) \
if(rc == #x##sv) return x
_CONVERT_(constqp);
_CONVERT_(vbr);
_CONVERT_(cbr);
@ -78,12 +80,12 @@ std::optional<rc_e> rc_from_view(const std::string_view &rc) {
int coder_from_view(const std::string_view &coder) {
if(coder == "auto"sv) return _auto;
if(coder == "cabac"sv || coder == "ac"sv) return cabac;
if(coder == "cavlc"sv || coder == "vlc"sv) return cavlc;
if(coder == "cabac"sv || coder == "ac"sv) return cabac;
if(coder == "cavlc"sv || coder == "vlc"sv) return cavlc;
return -1;
}
}
} // namespace nv
namespace amd {
enum quality_e : int {
@ -107,7 +109,8 @@ enum coder_e : int {
};
std::optional<quality_e> quality_from_view(const std::string_view &quality) {
#define _CONVERT_(x) if(quality == #x##sv) return x
#define _CONVERT_(x) \
if(quality == #x##sv) return x
_CONVERT_(speed);
_CONVERT_(balanced);
//_CONVERT_(quality2);
@ -117,7 +120,8 @@ std::optional<quality_e> quality_from_view(const std::string_view &quality) {
}
std::optional<rc_e> rc_from_view(const std::string_view &rc) {
#define _CONVERT_(x) if(rc == #x##sv) return x
#define _CONVERT_(x) \
if(rc == #x##sv) return x
_CONVERT_(constqp);
_CONVERT_(vbr_latency);
_CONVERT_(vbr_peak);
@ -128,40 +132,38 @@ std::optional<rc_e> rc_from_view(const std::string_view &rc) {
int coder_from_view(const std::string_view &coder) {
if(coder == "auto"sv) return _auto;
if(coder == "cabac"sv || coder == "ac"sv) return cabac;
if(coder == "cavlc"sv || coder == "vlc"sv) return cavlc;
if(coder == "cabac"sv || coder == "ac"sv) return cabac;
if(coder == "cavlc"sv || coder == "vlc"sv) return cavlc;
return -1;
}
}
} // namespace amd
video_t video {
0, // crf
0, // crf
28, // qp
0, // hevc_mode
1, // min_threads
{
"superfast"s, // preset
"superfast"s, // preset
"zerolatency"s, // tune
}, // software
}, // software
{
nv::llhq,
std::nullopt,
-1
}, // nv
-1 }, // nv
{
amd::balanced,
std::nullopt,
-1
}, // amd
-1 }, // amd
{}, // encoder
{}, // adapter_name
{}, // output_name
{}, // output_name
};
audio_t audio {};
@ -172,7 +174,7 @@ stream_t stream {
APPS_JSON_PATH,
10, // fecPercentage
1 // channels
1 // channels
};
nvhttp_t nvhttp {
@ -181,18 +183,18 @@ nvhttp_t nvhttp {
CERTIFICATE_FILE,
boost::asio::ip::host_name(), // sunshine_name,
"sunshine_state.json"s // file_state
"sunshine_state.json"s // file_state
};
input_t input {
2s, // back_button_timeout
500ms, // key_repeat_delay
std::chrono::duration<double> { 1 / 24.9 } // key_repeat_period
2s, // back_button_timeout
500ms, // key_repeat_delay
std::chrono::duration<double> { 1 / 24.9 } // key_repeat_period
};
sunshine_t sunshine {
2, // min_log_level
0 // flags
0 // flags
};
bool whitespace(char ch) {
@ -213,7 +215,7 @@ std::optional<std::pair<std::string, std::string>> parse_line(std::string_view::
return std::nullopt;
}
auto end_name = std::find_if(std::make_reverse_iterator(eq), std::make_reverse_iterator(begin), std::not_fn(whitespace)).base();
auto end_name = std::find_if(std::make_reverse_iterator(eq), 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) };
@ -227,7 +229,7 @@ std::unordered_map<std::string, std::string> parse_config(std::string_view file_
while(pos < end) {
auto newline = std::find_if(pos, end, [](auto ch) { return ch == '\n' || ch == '\r'; });
auto var = parse_line(pos, newline);
auto var = parse_line(pos, newline);
pos = (*newline == '\r') ? newline + 2 : newline + 1;
if(!var) {
@ -271,7 +273,7 @@ void int_f(std::unordered_map<std::string, std::string> &vars, const std::string
}
auto &val = it->second;
input = util::from_chars(&val[0], &val[0] + val.size());
input = util::from_chars(&val[0], &val[0] + val.size());
vars.erase(it);
}
@ -284,7 +286,7 @@ void int_f(std::unordered_map<std::string, std::string> &vars, const std::string
}
auto &val = it->second;
input = util::from_chars(&val[0], &val[0] + val.size());
input = util::from_chars(&val[0], &val[0] + val.size());
vars.erase(it);
}
@ -319,15 +321,14 @@ void int_between_f(std::unordered_map<std::string, std::string> &vars, const std
}
bool to_bool(std::string &boolean) {
std::for_each(std::begin(boolean), std::end(boolean), [](char ch) { return (char)std::tolower(ch); });
std::for_each(std::begin(boolean), std::end(boolean), [](char ch) { return (char)std::tolower(ch); });
return
boolean == "true"sv ||
boolean == "yes"sv ||
boolean == "enable"sv ||
(std::find(std::begin(boolean), std::end(boolean), '1') != std::end(boolean));
return boolean == "true"sv ||
boolean == "yes"sv ||
boolean == "enable"sv ||
(std::find(std::begin(boolean), std::end(boolean), '1') != std::end(boolean));
}
void bool_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input) {
void bool_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input) {
std::string tmp;
string_f(vars, name, tmp);
@ -338,7 +339,7 @@ void bool_f(std::unordered_map<std::string, std::string> &vars, const std::strin
input = to_bool(tmp) ? 1 : 0;
}
void double_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, double &input) {
void double_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, double &input) {
std::string tmp;
string_f(vars, name, tmp);
@ -368,32 +369,33 @@ void double_between_f(std::unordered_map<std::string, std::string> &vars, const
}
void print_help(const char *name) {
std::cout <<
"Usage: "sv << name << " [options] [/path/to/configuration_file]"sv << std::endl <<
" Any configurable option can be overwritten with: \"name=value\""sv << std::endl << std::endl <<
" --help | print help"sv << 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::cout << "Usage: "sv << name << " [options] [/path/to/configuration_file]"sv << std::endl
<< " Any configurable option can be overwritten with: \"name=value\""sv << std::endl
<< std::endl
<< " --help | print help"sv << 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;
}
int apply_flags(const char *line) {
int ret = 0;
while(*line != '\0') {
switch(*line) {
case '0':
config::sunshine.flags[config::flag::PIN_STDIN].flip();
break;
case '1':
config::sunshine.flags[config::flag::FRESH_STATE].flip();
break;
case 'p':
config::sunshine.flags[config::flag::CONST_PIN].flip();
break;
default:
std::cout << "Warning: Unrecognized flag: ["sv << *line << ']' << std::endl;
ret = -1;
case '0':
config::sunshine.flags[config::flag::PIN_STDIN].flip();
break;
case '1':
config::sunshine.flags[config::flag::FRESH_STATE].flip();
break;
case 'p':
config::sunshine.flags[config::flag::CONST_PIN].flip();
break;
default:
std::cout << "Warning: Unrecognized flag: ["sv << *line << ']' << std::endl;
ret = -1;
}
++line;
@ -410,9 +412,7 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
int_f(vars, "crf", video.crf);
int_f(vars, "qp", video.qp);
int_f(vars, "min_threads", video.min_threads);
int_between_f(vars, "hevc_mode", video.hevc_mode, {
0, 3
});
int_between_f(vars, "hevc_mode", video.hevc_mode, { 0, 3 });
string_f(vars, "sw_preset", video.sw.preset);
string_f(vars, "sw_tune", video.sw.tune);
int_f(vars, "nv_preset", video.nv.preset, nv::preset_from_view);
@ -435,26 +435,18 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
string_f(vars, "audio_sink", audio.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 });
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() });
if(to != -1) {
stream.ping_timeout = std::chrono::milliseconds(to);
}
int_between_f(vars, "channels", stream.channels, {
1, std::numeric_limits<int>::max()
});
int_between_f(vars, "channels", stream.channels, { 1, std::numeric_limits<int>::max() });
string_f(vars, "file_apps", stream.file_apps);
int_between_f(vars, "fec_percentage", stream.fec_percentage, {
1, 100
});
int_between_f(vars, "fec_percentage", stream.fec_percentage, { 1, 100 });
to = std::numeric_limits<int>::min();
int_f(vars, "back_button_timeout", to);
@ -464,12 +456,10 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
}
double repeat_frequency { 0 };
double_between_f(vars, "key_repeat_frequency", repeat_frequency, {
0, std::numeric_limits<double>::max()
});
double_between_f(vars, "key_repeat_frequency", repeat_frequency, { 0, std::numeric_limits<double>::max() });
if(repeat_frequency > 0) {
config::input.key_repeat_period = std::chrono::duration<double> {1 / repeat_frequency };
config::input.key_repeat_period = std::chrono::duration<double> { 1 / repeat_frequency };
}
to = -1;
@ -479,9 +469,7 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
}
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
});
string_restricted_f(vars, "min_log_level", log_level_string, { "verbose"sv, "debug"sv, "info"sv, "warning"sv, "error"sv, "fatal"sv, "none"sv });
if(!log_level_string.empty()) {
if(log_level_string == "verbose"sv) {
@ -515,7 +503,7 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
}
if(sunshine.min_log_level <= 3) {
for(auto &[var,_] : vars) {
for(auto &[var, _] : vars) {
std::cout << "Warning: Unrecognized configurable option ["sv << var << ']' << std::endl;
}
}
@ -526,7 +514,7 @@ int parse(int argc, char *argv[]) {
std::unordered_map<std::string, std::string> cmd_vars;
for(auto x = argc -1; x > 0; --x) {
for(auto x = argc - 1; x > 0; --x) {
auto line = argv[x];
if(line == "--help"sv) {
@ -569,10 +557,9 @@ int parse(int argc, char *argv[]) {
auto vars = parse_config(std::string {
// Quick and dirty
std::istreambuf_iterator<char>(in),
std::istreambuf_iterator<char>()
});
std::istreambuf_iterator<char>() });
for(auto &[name,value] : cmd_vars) {
for(auto &[name, value] : cmd_vars) {
vars.insert_or_assign(std::move(name), std::move(value));
}
@ -580,4 +567,4 @@ int parse(int argc, char *argv[]) {
return 0;
}
}
} // namespace config

View file

@ -1,16 +1,16 @@
#ifndef SUNSHINE_CONFIG_H
#define SUNSHINE_CONFIG_H
#include <chrono>
#include <string>
#include <bitset>
#include <chrono>
#include <optional>
#include <string>
namespace config {
struct video_t {
// ffmpeg params
int crf; // higher == more compression and less quality
int qp; // higher == more compression and less quality, ignored if crf != 0
int qp; // higher == more compression and less quality, ignored if crf != 0
int hevc_mode;
@ -76,9 +76,9 @@ struct input_t {
namespace flag {
enum flag_e : std::size_t {
PIN_STDIN = 0, // Read PIN from stdin instead of http
FRESH_STATE, // Do not load or save state
FRESH_STATE, // Do not load or save state
FLAG_SIZE,
CONST_PIN= 4 // Use "universal" pin
CONST_PIN = 4 // Use "universal" pin
};
}
@ -96,6 +96,6 @@ extern input_t input;
extern sunshine_t sunshine;
int parse(int argc, char *argv[]);
}
} // namespace config
#endif

View file

@ -2,14 +2,14 @@
// Created by loki on 5/31/19.
//
#include <openssl/pem.h>
#include "crypto.h"
#include <openssl/pem.h>
namespace crypto {
using big_num_t = util::safe_ptr<BIGNUM, BN_free>;
using big_num_t = util::safe_ptr<BIGNUM, BN_free>;
//using rsa_t = util::safe_ptr<RSA, RSA_free>;
using asn1_string_t = util::safe_ptr<ASN1_STRING, ASN1_STRING_free>;
cert_chain_t::cert_chain_t() : _certs {}, _cert_ctx {X509_STORE_CTX_new() } {}
cert_chain_t::cert_chain_t() : _certs {}, _cert_ctx { X509_STORE_CTX_new() } {}
void cert_chain_t::add(x509_t &&cert) {
x509_store_t x509_store { X509_STORE_new() };
@ -26,7 +26,7 @@ void cert_chain_t::add(x509_t &&cert) {
*/
const char *cert_chain_t::verify(x509_t::element_type *cert) {
int err_code = 0;
for(auto &[_,x509_store] : _certs) {
for(auto &[_, x509_store] : _certs) {
auto fg = util::fail_guard([this]() {
X509_STORE_CTX_cleanup(_cert_ctx.get());
});
@ -36,7 +36,7 @@ const char *cert_chain_t::verify(x509_t::element_type *cert) {
auto err = X509_verify_cert(_cert_ctx.get());
if (err == 1) {
if(err == 1) {
return nullptr;
}
@ -46,7 +46,7 @@ const char *cert_chain_t::verify(x509_t::element_type *cert) {
if(err_code == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
return nullptr;
}
if (err_code != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && err_code != X509_V_ERR_INVALID_CA) {
if(err_code != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && err_code != X509_V_ERR_INVALID_CA) {
return X509_verify_cert_error_string(err_code);
}
}
@ -63,7 +63,7 @@ int cipher_t::decrypt(const std::string_view &cipher, std::vector<std::uint8_t>
});
// Gen 7 servers use 128-bit AES ECB
if (EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_ecb(), nullptr, key.data(), nullptr) != 1) {
if(EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_ecb(), nullptr, key.data(), nullptr) != 1) {
return -1;
}
@ -72,11 +72,11 @@ int cipher_t::decrypt(const std::string_view &cipher, std::vector<std::uint8_t>
plaintext.resize((cipher.size() + 15) / 16 * 16);
auto size = (int)plaintext.size();
// Encrypt into the caller's buffer, leaving room for the auth tag to be prepended
if (EVP_DecryptUpdate(ctx.get(), plaintext.data(), &size, (const std::uint8_t*)cipher.data(), cipher.size()) != 1) {
if(EVP_DecryptUpdate(ctx.get(), plaintext.data(), &size, (const std::uint8_t *)cipher.data(), cipher.size()) != 1) {
return -1;
}
if (EVP_DecryptFinal_ex(ctx.get(), plaintext.data(), &len) != 1) {
if(EVP_DecryptFinal_ex(ctx.get(), plaintext.data(), &len) != 1) {
return -1;
}
@ -85,7 +85,7 @@ int cipher_t::decrypt(const std::string_view &cipher, std::vector<std::uint8_t>
}
int cipher_t::decrypt_gcm(aes_t &iv, const std::string_view &tagged_cipher,
std::vector<std::uint8_t> &plaintext) {
std::vector<std::uint8_t> &plaintext) {
auto cipher = tagged_cipher.substr(16);
auto tag = tagged_cipher.substr(0, 16);
@ -93,15 +93,15 @@ int cipher_t::decrypt_gcm(aes_t &iv, const std::string_view &tagged_cipher,
EVP_CIPHER_CTX_reset(ctx.get());
});
if (EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_gcm(), nullptr, nullptr, nullptr) != 1) {
if(EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_gcm(), nullptr, nullptr, nullptr) != 1) {
return -1;
}
if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, iv.size(), nullptr) != 1) {
if(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, iv.size(), nullptr) != 1) {
return -1;
}
if (EVP_DecryptInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data()) != 1) {
if(EVP_DecryptInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data()) != 1) {
return -1;
}
@ -109,16 +109,16 @@ int cipher_t::decrypt_gcm(aes_t &iv, const std::string_view &tagged_cipher,
plaintext.resize((cipher.size() + 15) / 16 * 16);
int size;
if (EVP_DecryptUpdate(ctx.get(), plaintext.data(), &size, (const std::uint8_t*)cipher.data(), cipher.size()) != 1) {
if(EVP_DecryptUpdate(ctx.get(), plaintext.data(), &size, (const std::uint8_t *)cipher.data(), cipher.size()) != 1) {
return -1;
}
if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(), const_cast<char*>(tag.data())) != 1) {
if(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(), const_cast<char *>(tag.data())) != 1) {
return -1;
}
int len = size;
if (EVP_DecryptFinal_ex(ctx.get(), plaintext.data() + size, &len) != 1) {
if(EVP_DecryptFinal_ex(ctx.get(), plaintext.data() + size, &len) != 1) {
return -1;
}
@ -134,7 +134,7 @@ int cipher_t::encrypt(const std::string_view &plaintext, std::vector<std::uint8_
});
// Gen 7 servers use 128-bit AES ECB
if (EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_ecb(), nullptr, key.data(), nullptr) != 1) {
if(EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_ecb(), nullptr, key.data(), nullptr) != 1) {
return -1;
}
@ -143,11 +143,11 @@ int cipher_t::encrypt(const std::string_view &plaintext, std::vector<std::uint8_
cipher.resize((plaintext.size() + 15) / 16 * 16);
auto size = (int)cipher.size();
// Encrypt into the caller's buffer
if (EVP_EncryptUpdate(ctx.get(), cipher.data(), &size, (const std::uint8_t*)plaintext.data(), plaintext.size()) != 1) {
if(EVP_EncryptUpdate(ctx.get(), cipher.data(), &size, (const std::uint8_t *)plaintext.data(), plaintext.size()) != 1) {
return -1;
}
if (EVP_EncryptFinal_ex(ctx.get(), cipher.data() + size, &len) != 1) {
if(EVP_EncryptFinal_ex(ctx.get(), cipher.data() + size, &len) != 1) {
return -1;
}
@ -230,14 +230,14 @@ std::string_view signature(const x509_t &x) {
const ASN1_BIT_STRING *asn1 = nullptr;
X509_get0_signature(&asn1, nullptr, x.get());
return { (const char*)asn1->data, (std::size_t)asn1->length };
return { (const char *)asn1->data, (std::size_t)asn1->length };
}
std::string rand(std::size_t bytes) {
std::string r;
r.resize(bytes);
RAND_bytes((uint8_t*)r.data(), r.size());
RAND_bytes((uint8_t *)r.data(), r.size());
return r;
}
@ -297,8 +297,8 @@ creds_t gen_creds(const std::string_view &cn, std::uint32_t key_bits) {
X509_set_pubkey(x509.get(), pkey.get());
auto name = X509_get_subject_name(x509.get());
X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC,
(const std::uint8_t*)cn.data(), cn.size(),
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
(const std::uint8_t *)cn.data(), cn.size(),
-1, 0);
X509_set_issuer_name(x509.get(), name);
@ -324,7 +324,7 @@ bool verify(const x509_t &x509, const std::string_view &data, const std::string_
return false;
}
if(EVP_DigestVerifyFinal(ctx.get(), (const uint8_t*)signature.data(), signature.size()) != 1) {
if(EVP_DigestVerifyFinal(ctx.get(), (const uint8_t *)signature.data(), signature.size()) != 1) {
return false;
}
@ -338,4 +338,4 @@ bool verify256(const x509_t &x509, const std::string_view &data, const std::stri
void md_ctx_destroy(EVP_MD_CTX *ctx) {
EVP_MD_CTX_destroy(ctx);
}
}
} // namespace crypto

View file

@ -5,12 +5,12 @@
#ifndef SUNSHINE_CRYPTO_H
#define SUNSHINE_CRYPTO_H
#include <cassert>
#include <array>
#include <cassert>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
#include "utility.h"
@ -25,14 +25,14 @@ void md_ctx_destroy(EVP_MD_CTX *);
using sha256_t = std::array<std::uint8_t, SHA256_DIGEST_LENGTH>;
using aes_t = std::array<std::uint8_t, 16>;
using x509_t = util::safe_ptr<X509, X509_free>;
using x509_store_t = util::safe_ptr<X509_STORE, X509_STORE_free>;
using aes_t = std::array<std::uint8_t, 16>;
using x509_t = util::safe_ptr<X509, X509_free>;
using x509_store_t = util::safe_ptr<X509_STORE, X509_STORE_free>;
using x509_store_ctx_t = util::safe_ptr<X509_STORE_CTX, X509_STORE_CTX_free>;
using cipher_ctx_t = util::safe_ptr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
using md_ctx_t = util::safe_ptr<EVP_MD_CTX, md_ctx_destroy>;
using bio_t = util::safe_ptr<BIO, BIO_free_all>;
using pkey_t = util::safe_ptr<EVP_PKEY, EVP_PKEY_free>;
using cipher_ctx_t = util::safe_ptr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
using md_ctx_t = util::safe_ptr<EVP_MD_CTX, md_ctx_destroy>;
using bio_t = util::safe_ptr<BIO, BIO_free_all>;
using pkey_t = util::safe_ptr<EVP_PKEY, EVP_PKEY_free>;
sha256_t hash(const std::string_view &plaintext);
aes_t gen_aes_key(const std::array<uint8_t, 16> &salt, const std::string_view &pin);
@ -58,6 +58,7 @@ public:
void add(x509_t &&cert);
const char *verify(x509_t::element_type *cert);
private:
std::vector<std::pair<x509_t, x509_store_t>> _certs;
x509_store_ctx_t _cert_ctx;
@ -66,13 +67,14 @@ private:
class cipher_t {
public:
cipher_t(const aes_t &key);
cipher_t(cipher_t&&) noexcept = default;
cipher_t &operator=(cipher_t&&) noexcept = default;
cipher_t(cipher_t &&) noexcept = default;
cipher_t &operator=(cipher_t &&) noexcept = default;
int encrypt(const std::string_view &plaintext, std::vector<std::uint8_t> &cipher);
int decrypt_gcm(aes_t &iv, const std::string_view &cipher, std::vector<std::uint8_t> &plaintext);
int decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext);
private:
cipher_ctx_t ctx;
aes_t key;
@ -80,6 +82,6 @@ private:
public:
bool padding;
};
}
} // namespace crypto
#endif //SUNSHINE_CRYPTO_H

View file

@ -10,16 +10,16 @@ extern "C" {
#include <bitset>
#include "main.h"
#include "config.h"
#include "utility.h"
#include "thread_pool.h"
#include "input.h"
#include "main.h"
#include "platform/common.h"
#include "thread_pool.h"
#include "utility.h"
namespace input {
constexpr auto MAX_GAMEPADS = std::min((std::size_t)platf::MAX_GAMEPADS, sizeof(std::int16_t)*8);
constexpr auto MAX_GAMEPADS = std::min((std::size_t)platf::MAX_GAMEPADS, sizeof(std::int16_t) * 8);
#define DISABLE_LEFT_BUTTON_DELAY ((util::ThreadPool::task_id_t)0x01)
#define ENABLE_LEFT_BUTTON_DELAY nullptr
@ -59,7 +59,7 @@ static platf::input_t platf_input;
static std::bitset<platf::MAX_GAMEPADS> gamepadMask {};
void free_gamepad(platf::input_t &platf_input, int id) {
platf::gamepad(platf_input, id, platf::gamepad_state_t{});
platf::gamepad(platf_input, id, platf::gamepad_state_t {});
platf::free_gamepad(platf_input, id);
free_id(gamepadMask, id);
@ -68,7 +68,7 @@ struct gamepad_t {
gamepad_t() : gamepad_state {}, back_timeout_id {}, id { -1 }, back_button_state { button_state_e::NONE } {}
~gamepad_t() {
if(id >= 0) {
task_pool.push([id=this->id]() {
task_pool.push([id = this->id]() {
free_gamepad(platf_input, id);
});
}
@ -89,7 +89,7 @@ struct gamepad_t {
};
struct input_t {
input_t() : active_gamepad_state {}, gamepads (MAX_GAMEPADS), mouse_left_button_timeout {} { }
input_t() : active_gamepad_state {}, gamepads(MAX_GAMEPADS), mouse_left_button_timeout {} {}
std::uint16_t active_gamepad_state;
std::vector<gamepad_t> gamepads;
@ -158,33 +158,32 @@ void print(PNV_MULTI_CONTROLLER_PACKET packet) {
constexpr int PACKET_TYPE_SCROLL_OR_KEYBOARD = PACKET_TYPE_SCROLL;
void print(void *input) {
int input_type = util::endian::big(*(int*)input);
int input_type = util::endian::big(*(int *)input);
switch(input_type) {
case PACKET_TYPE_REL_MOUSE_MOVE:
print((PNV_REL_MOUSE_MOVE_PACKET)input);
break;
case PACKET_TYPE_ABS_MOUSE_MOVE:
print((PNV_ABS_MOUSE_MOVE_PACKET)input);
break;
case PACKET_TYPE_MOUSE_BUTTON:
print((PNV_MOUSE_BUTTON_PACKET)input);
break;
case PACKET_TYPE_SCROLL_OR_KEYBOARD:
{
char *tmp_input = (char*)input + 4;
if(tmp_input[0] == 0x0A) {
print((PNV_SCROLL_PACKET)input);
}
else {
print((PNV_KEYBOARD_PACKET)input);
}
break;
case PACKET_TYPE_REL_MOUSE_MOVE:
print((PNV_REL_MOUSE_MOVE_PACKET)input);
break;
case PACKET_TYPE_ABS_MOUSE_MOVE:
print((PNV_ABS_MOUSE_MOVE_PACKET)input);
break;
case PACKET_TYPE_MOUSE_BUTTON:
print((PNV_MOUSE_BUTTON_PACKET)input);
break;
case PACKET_TYPE_SCROLL_OR_KEYBOARD: {
char *tmp_input = (char *)input + 4;
if(tmp_input[0] == 0x0A) {
print((PNV_SCROLL_PACKET)input);
}
case PACKET_TYPE_MULTI_CONTROLLER:
print((PNV_MULTI_CONTROLLER_PACKET)input);
break;
else {
print((PNV_KEYBOARD_PACKET)input);
}
break;
}
case PACKET_TYPE_MULTI_CONTROLLER:
print((PNV_MULTI_CONTROLLER_PACKET)input);
break;
}
}
@ -245,8 +244,8 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet
mouse_press[button] = !release;
}
///////////////////////////////////
/*/
///////////////////////////////////
/*/
* When Moonlight sends mouse input through absolute coordinates,
* it's possible that BUTTON_RIGHT is pressed down immediately after releasing BUTTON_LEFT.
* As a result, Sunshine will left click on hyperlinks in the browser before right clicking
@ -261,7 +260,7 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet
* when the last mouse coordinates were absolute
/*/
if(button == BUTTON_LEFT && release && !input->mouse_left_button_timeout) {
input->mouse_left_button_timeout = task_pool.pushDelayed([=]() {
auto f = [=]() {
auto left_released = mouse_press[BUTTON_LEFT];
if(left_released) {
// Already released left button
@ -269,16 +268,17 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet
}
platf::button_mouse(platf_input, BUTTON_LEFT, release);
mouse_press[BUTTON_LEFT] = false;
mouse_press[BUTTON_LEFT] = false;
input->mouse_left_button_timeout = nullptr;
}, 10ms).task_id;
};
input->mouse_left_button_timeout = task_pool.pushDelayed(std::move(f), 10ms).task_id;
return;
}
if(
button == BUTTON_RIGHT && !release &&
input->mouse_left_button_timeout > DISABLE_LEFT_BUTTON_DELAY
) {
input->mouse_left_button_timeout > DISABLE_LEFT_BUTTON_DELAY) {
platf::button_mouse(platf_input, BUTTON_RIGHT, false);
platf::button_mouse(platf_input, BUTTON_RIGHT, true);
@ -286,7 +286,7 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet
return;
}
///////////////////////////////////
///////////////////////////////////
platf::button_mouse(platf_input, button, release);
}
@ -341,7 +341,7 @@ void passthrough(PNV_SCROLL_PACKET packet) {
int updateGamepads(std::vector<gamepad_t> &gamepads, std::int16_t old_state, std::int16_t new_state) {
auto xorGamepadMask = old_state ^ new_state;
if (!xorGamepadMask) {
if(!xorGamepadMask) {
return 0;
}
@ -350,7 +350,7 @@ int updateGamepads(std::vector<gamepad_t> &gamepads, std::int16_t old_state, std
auto &gamepad = gamepads[x];
if((old_state >> x) & 1) {
if (gamepad.id < 0) {
if(gamepad.id < 0) {
return -1;
}
@ -410,7 +410,7 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET pa
display_cursor = false;
std::uint16_t bf = packet->buttonFlags;
platf::gamepad_state_t gamepad_state{
platf::gamepad_state_t gamepad_state {
bf,
packet->leftTrigger,
packet->rightTrigger,
@ -422,30 +422,30 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET pa
auto bf_new = gamepad_state.buttonFlags;
switch(gamepad.back_button_state) {
case button_state_e::UP:
if(!(platf::BACK & bf_new)) {
gamepad.back_button_state = button_state_e::NONE;
}
gamepad_state.buttonFlags &= ~platf::BACK;
break;
case button_state_e::DOWN:
if(platf::BACK & bf_new) {
gamepad.back_button_state = button_state_e::NONE;
}
gamepad_state.buttonFlags |= platf::BACK;
break;
case button_state_e::NONE:
break;
case button_state_e::UP:
if(!(platf::BACK & bf_new)) {
gamepad.back_button_state = button_state_e::NONE;
}
gamepad_state.buttonFlags &= ~platf::BACK;
break;
case button_state_e::DOWN:
if(platf::BACK & bf_new) {
gamepad.back_button_state = button_state_e::NONE;
}
gamepad_state.buttonFlags |= platf::BACK;
break;
case button_state_e::NONE:
break;
}
bf = gamepad_state.buttonFlags ^ gamepad.gamepad_state.buttonFlags;
bf = gamepad_state.buttonFlags ^ gamepad.gamepad_state.buttonFlags;
bf_new = gamepad_state.buttonFlags;
if (platf::BACK & bf) {
if (platf::BACK & bf_new) {
if(platf::BACK & bf) {
if(platf::BACK & bf_new) {
// Don't emulate home button if timeout < 0
if(config::input.back_button_timeout >= 0ms) {
gamepad.back_timeout_id = task_pool.pushDelayed([input, controller=packet->controllerNumber]() {
auto f = [input, controller = packet->controllerNumber]() {
auto &gamepad = input->gamepads[controller];
auto &state = gamepad.gamepad_state;
@ -464,10 +464,12 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET pa
platf::gamepad(platf_input, gamepad.id, state);
gamepad.back_timeout_id = nullptr;
}, config::input.back_button_timeout).task_id;
};
gamepad.back_timeout_id = task_pool.pushDelayed(std::move(f), config::input.back_button_timeout).task_id;
}
}
else if (gamepad.back_timeout_id) {
else if(gamepad.back_timeout_id) {
task_pool.cancel(gamepad.back_timeout_id);
gamepad.back_timeout_id = nullptr;
}
@ -481,33 +483,32 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET pa
void passthrough_helper(std::shared_ptr<input_t> input, std::vector<std::uint8_t> &&input_data) {
void *payload = input_data.data();
int input_type = util::endian::big(*(int*)payload);
int input_type = util::endian::big(*(int *)payload);
switch(input_type) {
case PACKET_TYPE_REL_MOUSE_MOVE:
passthrough(input, (PNV_REL_MOUSE_MOVE_PACKET)payload);
break;
case PACKET_TYPE_ABS_MOUSE_MOVE:
passthrough(input, (PNV_ABS_MOUSE_MOVE_PACKET)payload);
break;
case PACKET_TYPE_MOUSE_BUTTON:
passthrough(input, (PNV_MOUSE_BUTTON_PACKET)payload);
break;
case PACKET_TYPE_SCROLL_OR_KEYBOARD:
{
char *tmp_input = (char*)payload + 4;
if(tmp_input[0] == 0x0A) {
passthrough((PNV_SCROLL_PACKET)payload);
}
else {
passthrough(input, (PNV_KEYBOARD_PACKET)payload);
}
break;
case PACKET_TYPE_REL_MOUSE_MOVE:
passthrough(input, (PNV_REL_MOUSE_MOVE_PACKET)payload);
break;
case PACKET_TYPE_ABS_MOUSE_MOVE:
passthrough(input, (PNV_ABS_MOUSE_MOVE_PACKET)payload);
break;
case PACKET_TYPE_MOUSE_BUTTON:
passthrough(input, (PNV_MOUSE_BUTTON_PACKET)payload);
break;
case PACKET_TYPE_SCROLL_OR_KEYBOARD: {
char *tmp_input = (char *)payload + 4;
if(tmp_input[0] == 0x0A) {
passthrough((PNV_SCROLL_PACKET)payload);
}
case PACKET_TYPE_MULTI_CONTROLLER:
passthrough(input, (PNV_MULTI_CONTROLLER_PACKET)payload);
break;
else {
passthrough(input, (PNV_KEYBOARD_PACKET)payload);
}
break;
}
case PACKET_TYPE_MULTI_CONTROLLER:
passthrough(input, (PNV_MULTI_CONTROLLER_PACKET)payload);
break;
}
}
@ -528,7 +529,7 @@ void reset(std::shared_ptr<input_t> &input) {
}
}
for(auto& kp : key_press) {
for(auto &kp : key_press) {
platf::keyboard(platf_input, kp.first & 0x00FF, true);
key_press[kp.first] = false;
}
@ -537,7 +538,7 @@ void reset(std::shared_ptr<input_t> &input) {
void init() {
touch_port_event = std::make_unique<touch_port_event_t::element_type>();
platf_input = platf::input();
platf_input = platf::input();
}
std::shared_ptr<input_t> alloc() {
@ -547,8 +548,9 @@ std::shared_ptr<input_t> alloc() {
task_pool.pushDelayed([]() {
platf::move_mouse(platf_input, 1, 1);
platf::move_mouse(platf_input, -1, -1);
}, 100ms);
},
100ms);
return input;
}
}
} // namespace input

View file

@ -5,8 +5,8 @@
#ifndef SUNSHINE_INPUT_H
#define SUNSHINE_INPUT_H
#include "thread_safe.h"
#include "platform/common.h"
#include "thread_safe.h"
namespace input {
struct input_t;
@ -22,6 +22,6 @@ std::shared_ptr<input_t> alloc();
using touch_port_event_t = std::unique_ptr<safe::event_t<platf::touch_port_t>>;
extern touch_port_event_t touch_port_event;
}
} // namespace input
#endif //SUNSHINE_INPUT_H

View file

@ -4,26 +4,26 @@
#include "process.h"
#include <thread>
#include <iostream>
#include <csignal>
#include <iostream>
#include <thread>
#include <boost/log/common.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/attributes/clock.hpp>
#include <boost/log/common.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include "video.h"
#include "config.h"
#include "nvhttp.h"
#include "rtsp.h"
#include "config.h"
#include "thread_pool.h"
#include "video.h"
#include "platform/common.h"
extern "C" {
#include <rs.h>
#include <libavutil/log.h>
#include <rs.h>
}
using namespace std::literals;
@ -79,31 +79,31 @@ int main(int argc, char *argv[]) {
sink->locked_backend()->add_stream(stream);
sink->set_filter(severity >= config::sunshine.min_log_level);
sink->set_formatter([message="Message"s, severity="Severity"s](const bl::record_view &view, bl::formatting_ostream &os) {
constexpr int DATE_BUFFER_SIZE = 21 +2 +1; // Full string plus ": \0"
sink->set_formatter([message = "Message"s, severity = "Severity"s](const bl::record_view &view, bl::formatting_ostream &os) {
constexpr int DATE_BUFFER_SIZE = 21 + 2 + 1; // Full string plus ": \0"
auto log_level = view.attribute_values()[severity].extract<int>().get();
std::string_view log_type;
switch(log_level) {
case 0:
log_type = "Verbose: "sv;
break;
case 1:
log_type = "Debug: "sv;
break;
case 2:
log_type = "Info: "sv;
break;
case 3:
log_type = "Warning: "sv;
break;
case 4:
log_type = "Error: "sv;
break;
case 5:
log_type = "Fatal: "sv;
break;
case 0:
log_type = "Verbose: "sv;
break;
case 1:
log_type = "Debug: "sv;
break;
case 2:
log_type = "Info: "sv;
break;
case 3:
log_type = "Warning: "sv;
break;
case 4:
log_type = "Error: "sv;
break;
case 5:
log_type = "Fatal: "sv;
break;
};
char _date[DATE_BUFFER_SIZE];

View file

@ -5,8 +5,8 @@
#ifndef SUNSHINE_MAIN_H
#define SUNSHINE_MAIN_H
#include <boost/log/common.hpp>
#include "thread_pool.h"
#include <boost/log/common.hpp>
extern util::ThreadPool task_pool;
extern bool display_cursor;

View file

@ -11,23 +11,24 @@ template<class T>
class MoveByCopy {
public:
typedef T move_type;
private:
move_type _to_move;
public:
explicit MoveByCopy(move_type &&to_move) : _to_move(std::move(to_move)) { }
public:
explicit MoveByCopy(move_type &&to_move) : _to_move(std::move(to_move)) {}
MoveByCopy(MoveByCopy &&other) = default;
MoveByCopy(const MoveByCopy &other) {
*this = other;
}
MoveByCopy& operator=(MoveByCopy &&other) = default;
MoveByCopy& operator=(const MoveByCopy &other) {
this->_to_move = std::move(const_cast<MoveByCopy&>(other)._to_move);
MoveByCopy &operator=(MoveByCopy &&other) = default;
MoveByCopy &operator=(const MoveByCopy &other) {
this->_to_move = std::move(const_cast<MoveByCopy &>(other)._to_move);
return *this;
}
@ -44,7 +45,7 @@ MoveByCopy<T> cmove(T &movable) {
// Do NOT use this unless you are absolutely certain the object to be moved is no longer used by the caller
template<class T>
MoveByCopy<T> const_cmove(const T &movable) {
return MoveByCopy<T>(std::move(const_cast<T&>(movable)));
}
return MoveByCopy<T>(std::move(const_cast<T &>(movable)));
}
} // namespace util
#endif

View file

@ -2,9 +2,9 @@
// Created by loki on 12/27/19.
//
#include <algorithm>
#include "network.h"
#include "utility.h"
#include <algorithm>
namespace net {
using namespace std::literals;
@ -21,17 +21,17 @@ std::vector<std::tuple<std::uint32_t, std::uint32_t>> lan_ips {
};
std::uint32_t ip(const std::string_view &ip_str) {
auto begin = std::begin(ip_str);
auto end = std::end(ip_str);
auto begin = std::begin(ip_str);
auto end = std::end(ip_str);
auto temp_end = std::find(begin, end, '.');
std::uint32_t ip = 0;
auto shift = 24;
auto shift = 24;
while(temp_end != end) {
ip += (util::from_chars(begin, temp_end) << shift);
shift -= 8;
begin = temp_end + 1;
begin = temp_end + 1;
temp_end = std::find(begin, end, '.');
}
@ -43,7 +43,7 @@ std::uint32_t ip(const std::string_view &ip_str) {
// In the format "xxx.xxx.xxx.xxx/x"
std::pair<std::uint32_t, std::uint32_t> ip_block(const std::string_view &ip_str) {
auto begin = std::begin(ip_str);
auto end = std::find(begin, std::end(ip_str), '/');
auto end = std::find(begin, std::end(ip_str), '/');
auto addr = ip({ begin, (std::size_t)(end - begin) });
@ -82,12 +82,12 @@ net_e from_address(const std::string_view &view) {
std::string_view to_enum_string(net_e net) {
switch(net) {
case PC:
return "pc"sv;
case LAN:
return "lan"sv;
case WAN:
return "wan"sv;
case PC:
return "pc"sv;
case LAN:
return "lan"sv;
case WAN:
return "wan"sv;
}
// avoid warning
@ -112,4 +112,4 @@ void free_host(ENetHost *host) {
enet_host_destroy(host);
}
}
} // namespace net

View file

@ -14,8 +14,8 @@
namespace net {
void free_host(ENetHost *host);
using host_t = util::safe_ptr<ENetHost, free_host>;
using peer_t = ENetPeer*;
using host_t = util::safe_ptr<ENetHost, free_host>;
using peer_t = ENetPeer *;
using packet_t = util::safe_ptr<ENetPacket, enet_packet_destroy>;
enum net_e : int {
@ -30,6 +30,6 @@ std::string_view to_enum_string(net_e net);
net_e from_address(const std::string_view &view);
host_t host_create(ENetAddress &addr, std::size_t peers, std::uint16_t port);
}
} // namespace net
#endif //SUNSHINE_NETWORK_H

View file

@ -6,9 +6,9 @@
#include <filesystem>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/asio/ssl/context.hpp>
@ -17,14 +17,14 @@
#include <boost/asio/ssl/context_base.hpp>
#include "config.h"
#include "utility.h"
#include "rtsp.h"
#include "crypto.h"
#include "main.h"
#include "network.h"
#include "nvhttp.h"
#include "platform/common.h"
#include "network.h"
#include "rtsp.h"
#include "utility.h"
#include "uuid.h"
#include "main.h"
namespace nvhttp {
@ -69,8 +69,8 @@ struct pair_session_t {
struct {
util::Either<
std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTP>::Response>,
std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTPS>::Response>
> response;
std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTPS>::Response>>
response;
std::string salt;
} async_insert_pin;
};
@ -81,11 +81,11 @@ std::unordered_map<std::string, client_t> map_id_client;
std::string unique_id;
net::net_e origin_pin_allowed;
using args_t = SimpleWeb::CaseInsensitiveMultimap;
using args_t = SimpleWeb::CaseInsensitiveMultimap;
using resp_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTPS>::Response>;
using req_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTPS>::Request>;
using resp_http_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTP>::Response>;
using req_http_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTP>::Request>;
using req_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTPS>::Request>;
using resp_http_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTP>::Response>;
using req_http_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTP>::Request>;
enum class op_e {
ADD,
@ -97,7 +97,7 @@ void save_state() {
root.put("root.uniqueid", unique_id);
auto &nodes = root.add_child("root.devices", pt::ptree {});
for(auto &[_,client] : map_id_client) {
for(auto &[_, client] : map_id_client) {
pt::ptree node;
node.put("uniqueid"s, client.uniqueID);
@ -127,17 +127,18 @@ void load_state() {
pt::ptree root;
try {
pt::read_json(config::nvhttp.file_state, root);
} catch (std::exception &e) {
}
catch(std::exception &e) {
BOOST_LOG(warning) << e.what();
return;
}
unique_id = root.get<std::string>("root.uniqueid");
unique_id = root.get<std::string>("root.uniqueid");
auto device_nodes = root.get_child("root.devices");
for(auto &[_,device_node] : device_nodes) {
auto uniqID = device_node.get<std::string>("uniqueid");
for(auto &[_, device_node] : device_nodes) {
auto uniqID = device_node.get<std::string>("uniqueid");
auto &client = map_id_client.emplace(uniqID, client_t {}).first->second;
client.uniqueID = uniqID;
@ -150,16 +151,14 @@ void load_state() {
void update_id_client(const std::string &uniqueID, std::string &&cert, op_e op) {
switch(op) {
case op_e::ADD:
{
auto &client = map_id_client[uniqueID];
client.certs.emplace_back(std::move(cert));
client.uniqueID = uniqueID;
}
break;
case op_e::REMOVE:
map_id_client.erase(uniqueID);
break;
case op_e::ADD: {
auto &client = map_id_client[uniqueID];
client.certs.emplace_back(std::move(cert));
client.uniqueID = uniqueID;
} break;
case op_e::REMOVE:
map_id_client.erase(uniqueID);
break;
}
if(!config::sunshine.flags[config::flag::FRESH_STATE]) {
@ -175,10 +174,10 @@ void getservercert(pair_session_t &sess, pt::ptree &tree, const std::string &pin
}
std::string_view salt_view { sess.async_insert_pin.salt.data(), 32 };
auto salt = util::from_hex<std::array<uint8_t, 16>>(salt_view, true);
auto key = crypto::gen_aes_key(*salt, pin);
auto key = crypto::gen_aes_key(*salt, pin);
sess.cipher_key = std::make_unique<crypto::aes_t>(key);
tree.put("root.paired", 1);
@ -197,7 +196,7 @@ void serverchallengeresp(pair_session_t &sess, pt::ptree &tree, const args_t &ar
sess.clienthash = std::move(decrypted);
auto serversecret = sess.serversecret;
auto sign = crypto::sign256(crypto::pkey(conf_intern.pkey), serversecret);
auto sign = crypto::sign256(crypto::pkey(conf_intern.pkey), serversecret);
serversecret.insert(std::end(serversecret), std::begin(sign), std::end(sign));
@ -215,14 +214,14 @@ void clientchallenge(pair_session_t &sess, pt::ptree &tree, const args_t &args)
std::vector<uint8_t> decrypted;
cipher.decrypt(challenge, decrypted);
auto x509 = crypto::x509(conf_intern.servercert);
auto sign = crypto::signature(x509);
auto x509 = crypto::x509(conf_intern.servercert);
auto sign = crypto::signature(x509);
auto serversecret = crypto::rand(16);
decrypted.insert(std::end(decrypted), std::begin(sign), std::end(sign));
decrypted.insert(std::end(decrypted), std::begin(serversecret), std::end(serversecret));
auto hash = crypto::hash({ (char*)decrypted.data(), decrypted.size() });
auto hash = crypto::hash({ (char *)decrypted.data(), decrypted.size() });
auto serverchallenge = crypto::rand(16);
std::string plaintext;
@ -252,7 +251,7 @@ void clientpairingsecret(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cer
assert((secret.size() + sign.size()) == pairingsecret.size());
auto x509 = crypto::x509(client.cert);
auto x509 = crypto::x509(client.cert);
auto x509_sign = crypto::signature(x509);
std::string data;
@ -306,8 +305,8 @@ template<class T>
void print_req(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
BOOST_LOG(debug) << "TUNNEL :: "sv << tunnel<T>::to_string;
BOOST_LOG(debug) << "METHOD :: "sv << request->method;
BOOST_LOG(debug) << "DESTINATION :: "sv << request->path;
BOOST_LOG(debug) << "METHOD :: "sv << request->method;
BOOST_LOG(debug) << "DESTINATION :: "sv << request->path;
for(auto &[name, val] : request->header) {
BOOST_LOG(debug) << name << " -- " << val;
@ -334,7 +333,8 @@ void not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> resp
pt::write_xml(data, tree);
response->write(data.str());
*response << "HTTP/1.1 404 NOT FOUND\r\n" << data.str();
*response << "HTTP/1.1 404 NOT FOUND\r\n"
<< data.str();
}
template<class T>
@ -351,9 +351,9 @@ void pair(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, std::shared_
if(it = args.find("phrase"); it != std::end(args)) {
if(it->second == "getservercert"sv) {
pair_session_t sess;
sess.client.uniqueID = std::move(uniqID);
sess.client.cert = util::from_hex_vec(args.at("clientcert"s), true);
sess.client.cert = util::from_hex_vec(args.at("clientcert"s), true);
BOOST_LOG(debug) << sess.client.cert;
auto ptr = map_id_sess.emplace(sess.client.uniqueID, std::move(sess)).first;
@ -435,7 +435,7 @@ void pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response,
if(async_response.has_left() && async_response.left()) {
async_response.left()->write(data.str());
}
else if(async_response.has_right() && async_response.right()){
else if(async_response.has_right() && async_response.right()) {
async_response.right()->write(data.str());
}
else {
@ -455,13 +455,13 @@ void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> res
print_req<T>(request);
int pair_status = 0;
if constexpr (std::is_same_v<SimpleWeb::HTTPS, T>) {
auto args = request->parse_query_string();
if constexpr(std::is_same_v<SimpleWeb::HTTPS, T>) {
auto args = request->parse_query_string();
auto clientID = args.find("uniqueid"s);
if(clientID != std::end(args)) {
if (auto it = map_id_client.find(clientID->second); it != std::end(map_id_client)) {
if(auto it = map_id_client.find(clientID->second); it != std::end(map_id_client)) {
pair_status = 1;
}
}
@ -507,7 +507,7 @@ void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> res
void applist(resp_https_t response, req_https_t request) {
print_req<SimpleWeb::HTTPS>(request);
auto args = request->parse_query_string();
auto args = request->parse_query_string();
auto clientID = args.at("uniqueid"s);
pt::ptree tree;
@ -560,8 +560,8 @@ void launch(resp_https_t response, req_https_t request) {
return;
}
auto args = request->parse_query_string();
auto appid = util::from_view(args.at("appid")) -1;
auto args = request->parse_query_string();
auto appid = util::from_view(args.at("appid")) - 1;
auto current_appid = proc::proc.running();
if(current_appid != -1) {
@ -583,10 +583,10 @@ void launch(resp_https_t response, req_https_t request) {
stream::launch_session_t launch_session;
auto clientID = args.at("uniqueid"s);
auto clientID = args.at("uniqueid"s);
launch_session.gcm_key = *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)));
auto prepend_iv_p = (uint8_t*)&prepend_iv;
uint32_t prepend_iv = util::endian::big<uint32_t>(util::from_view(args.at("rikeyid"s)));
auto prepend_iv_p = (uint8_t *)&prepend_iv;
auto next = std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv));
std::fill(next, std::end(launch_session.iv), 0);
@ -627,11 +627,11 @@ void resume(resp_https_t response, req_https_t request) {
stream::launch_session_t launch_session;
auto args = request->parse_query_string();
auto clientID = args.at("uniqueid"s);
auto args = request->parse_query_string();
auto clientID = args.at("uniqueid"s);
launch_session.gcm_key = *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)));
auto prepend_iv_p = (uint8_t*)&prepend_iv;
uint32_t prepend_iv = util::endian::big<uint32_t>(util::from_view(args.at("rikeyid"s)));
auto prepend_iv_p = (uint8_t *)&prepend_iv;
auto next = std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv));
std::fill(next, std::end(launch_session.iv), 0);
@ -688,25 +688,25 @@ int create_creds(const std::string &pkey, const std::string &cert) {
pkey_dir.remove_filename();
cert_dir.remove_filename();
std::error_code err_code{};
std::error_code err_code {};
fs::create_directories(pkey_dir, err_code);
if (err_code) {
if(err_code) {
BOOST_LOG(fatal) << "Couldn't create directory ["sv << pkey_dir << "] :"sv << err_code.message();
return -1;
}
fs::create_directories(cert_dir, err_code);
if (err_code) {
if(err_code) {
BOOST_LOG(fatal) << "Couldn't create directory ["sv << cert_dir << "] :"sv << err_code.message();
return -1;
}
if (write_file(pkey.c_str(), creds.pkey)) {
if(write_file(pkey.c_str(), creds.pkey)) {
BOOST_LOG(fatal) << "Couldn't open ["sv << config::nvhttp.pkey << ']';
return -1;
}
if (write_file(cert.c_str(), creds.x509)) {
if(write_file(cert.c_str(), creds.x509)) {
BOOST_LOG(fatal) << "Couldn't open ["sv << config::nvhttp.cert << ']';
return -1;
}
@ -715,7 +715,7 @@ int create_creds(const std::string &pkey, const std::string &cert) {
fs::perms::owner_read | fs::perms::owner_write,
fs::perm_options::replace, err_code);
if (err_code) {
if(err_code) {
BOOST_LOG(fatal) << "Couldn't change permissions of ["sv << config::nvhttp.pkey << "] :"sv << err_code.message();
return -1;
}
@ -724,7 +724,7 @@ int create_creds(const std::string &pkey, const std::string &cert) {
fs::perms::owner_read | fs::perms::group_read | fs::perms::others_read | fs::perms::owner_write,
fs::perm_options::replace, err_code);
if (err_code) {
if(err_code) {
BOOST_LOG(fatal) << "Couldn't change permissions of ["sv << config::nvhttp.cert << "] :"sv << err_code.message();
return -1;
}
@ -757,7 +757,7 @@ void start(std::shared_ptr<safe::signal_t> shutdown_event) {
load_state();
}
conf_intern.pkey = read_file(config::nvhttp.pkey.c_str());
conf_intern.pkey = read_file(config::nvhttp.pkey.c_str());
conf_intern.servercert = read_file(config::nvhttp.cert.c_str());
auto ctx = std::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tls);
@ -765,7 +765,7 @@ void start(std::shared_ptr<safe::signal_t> shutdown_event) {
ctx->use_private_key_file(config::nvhttp.pkey, boost::asio::ssl::context::pem);
crypto::cert_chain_t cert_chain;
for(auto &[_,client] : map_id_client) {
for(auto &[_, client] : map_id_client) {
for(auto &cert : client.certs) {
cert_chain.add(crypto::x509(cert));
}
@ -813,33 +813,34 @@ void start(std::shared_ptr<safe::signal_t> shutdown_event) {
https_server_t https_server { ctx, boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert | boost::asio::ssl::verify_client_once };
http_server_t http_server;
https_server.default_resource = not_found<SimpleWeb::HTTPS>;
https_server.resource["^/serverinfo$"]["GET"] = serverinfo<SimpleWeb::HTTPS>;
https_server.resource["^/pair$"]["GET"] = [&add_cert](auto resp, auto req) { pair<SimpleWeb::HTTPS>(add_cert, resp, req); };
https_server.resource["^/applist$"]["GET"] = applist;
https_server.resource["^/appasset$"]["GET"] = appasset;
https_server.resource["^/launch$"]["GET"] = launch;
https_server.default_resource = not_found<SimpleWeb::HTTPS>;
https_server.resource["^/serverinfo$"]["GET"] = serverinfo<SimpleWeb::HTTPS>;
https_server.resource["^/pair$"]["GET"] = [&add_cert](auto resp, auto req) { pair<SimpleWeb::HTTPS>(add_cert, resp, req); };
https_server.resource["^/applist$"]["GET"] = applist;
https_server.resource["^/appasset$"]["GET"] = appasset;
https_server.resource["^/launch$"]["GET"] = launch;
https_server.resource["^/pin/([0-9]+)$"]["GET"] = pin<SimpleWeb::HTTPS>;
https_server.resource["^/resume$"]["GET"] = resume;
https_server.resource["^/cancel$"]["GET"] = cancel;
https_server.resource["^/resume$"]["GET"] = resume;
https_server.resource["^/cancel$"]["GET"] = cancel;
https_server.config.reuse_address = true;
https_server.config.address = "0.0.0.0"s;
https_server.config.port = PORT_HTTPS;
https_server.config.address = "0.0.0.0"s;
https_server.config.port = PORT_HTTPS;
http_server.default_resource = not_found<SimpleWeb::HTTP>;
http_server.resource["^/serverinfo$"]["GET"] = serverinfo<SimpleWeb::HTTP>;
http_server.resource["^/pair$"]["GET"] = [&add_cert](auto resp, auto req) { pair<SimpleWeb::HTTP>(add_cert, resp, req); };
http_server.default_resource = not_found<SimpleWeb::HTTP>;
http_server.resource["^/serverinfo$"]["GET"] = serverinfo<SimpleWeb::HTTP>;
http_server.resource["^/pair$"]["GET"] = [&add_cert](auto resp, auto req) { pair<SimpleWeb::HTTP>(add_cert, resp, req); };
http_server.resource["^/pin/([0-9]+)$"]["GET"] = pin<SimpleWeb::HTTP>;
http_server.config.reuse_address = true;
http_server.config.address = "0.0.0.0"s;
http_server.config.port = PORT_HTTP;
http_server.config.address = "0.0.0.0"s;
http_server.config.port = PORT_HTTP;
try {
https_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();
shutdown_event->raise(true);
@ -849,7 +850,8 @@ void start(std::shared_ptr<safe::signal_t> shutdown_event) {
auto accept_and_run = [&](auto *http_server) {
try {
http_server->accept_and_run();
} catch(boost::system::system_error &err) {
}
catch(boost::system::system_error &err) {
// It's possible the exception gets thrown after calling http_server->stop() from a different thread
if(shutdown_event->peek()) {
return;
@ -899,4 +901,4 @@ std::string read_file(const char *path) {
return base64_cert;
}
}
} // namespace nvhttp

View file

@ -11,8 +11,8 @@
#include "thread_safe.h"
#define CA_DIR SUNSHINE_ASSETS_DIR "/demoCA"
#define PRIVATE_KEY_FILE CA_DIR "/cakey.pem"
#define CERTIFICATE_FILE CA_DIR "/cacert.pem"
#define PRIVATE_KEY_FILE CA_DIR "/cakey.pem"
#define CERTIFICATE_FILE CA_DIR "/cacert.pem"
namespace nvhttp {
void start(std::shared_ptr<safe::signal_t> shutdown_event);

View file

@ -5,9 +5,9 @@
#ifndef SUNSHINE_COMMON_H
#define SUNSHINE_COMMON_H
#include <string>
#include <mutex>
#include "sunshine/utility.h"
#include <mutex>
#include <string>
struct sockaddr;
namespace platf {
@ -44,8 +44,10 @@ enum class pix_fmt_e {
};
inline std::string_view from_pix_fmt(pix_fmt_e pix_fmt) {
using namespace std::literals;
#define _CONVERT(x) case pix_fmt_e:: x : return #x ## sv
using namespace std::literals;
#define _CONVERT(x) \
case pix_fmt_e::x: \
return #x##sv
switch(pix_fmt) {
_CONVERT(yuv420p);
_CONVERT(yuv420p10);
@ -65,9 +67,8 @@ struct touch_port_t {
constexpr touch_port_t(
std::uint32_t offset_x, std::uint32_t offset_y,
std::uint32_t width, std::uint32_t height) noexcept :
offset_x { offset_x }, offset_y { offset_y },
width { width }, height { height } {};
std::uint32_t width, std::uint32_t height) noexcept : offset_x { offset_x }, offset_y { offset_y },
width { width }, height { height } {};
};
struct gamepad_state_t {
@ -87,15 +88,15 @@ public:
struct img_t {
public:
std::uint8_t *data {};
std::int32_t width {};
std::uint8_t *data {};
std::int32_t width {};
std::int32_t height {};
std::int32_t pixel_pitch {};
std::int32_t row_pitch {};
img_t() = default;
img_t(const img_t&) = delete;
img_t(img_t&&) = delete;
img_t() = default;
img_t(const img_t &) = delete;
img_t(img_t &&) = delete;
virtual ~img_t() = default;
};
@ -124,7 +125,7 @@ class display_t {
public:
display_t() noexcept : offset_x { 0 }, offset_y { 0 } {}
virtual capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) = 0;
virtual std::shared_ptr<img_t> alloc_img() = 0;
virtual std::shared_ptr<img_t> alloc_img() = 0;
virtual int dummy_img(img_t *img) = 0;
@ -148,7 +149,7 @@ public:
};
void freeInput(void*);
void freeInput(void *);
using input_t = util::safe_ptr<void, freeInput>;
@ -172,6 +173,6 @@ int alloc_gamepad(input_t &input, int nr);
void free_gamepad(input_t &input, int nr);
[[nodiscard]] std::unique_ptr<deinit_t> init();
}
} // namespace platf
#endif //SUNSHINE_COMMON_H

View file

@ -4,8 +4,8 @@
#include "sunshine/platform/common.h"
#include <fstream>
#include <bitset>
#include <fstream>
#include <arpa/inet.h>
#include <ifaddrs.h>
@ -15,36 +15,35 @@
#include <X11/Xutil.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/Xrandr.h>
#include <xcb/shm.h>
#include <xcb/xfixes.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <xcb/shm.h>
#include <xcb/xfixes.h>
#include <pulse/simple.h>
#include <pulse/error.h>
#include <pulse/simple.h>
#include "sunshine/task_pool.h"
#include "sunshine/config.h"
#include "sunshine/main.h"
#include "sunshine/task_pool.h"
namespace platf
{
namespace platf {
using namespace std::literals;
void freeImage(XImage*);
void freeX(XFixesCursorImage*);
void freeImage(XImage *);
void freeX(XFixesCursorImage *);
using ifaddr_t = util::safe_ptr<ifaddrs, freeifaddrs>;
using ifaddr_t = util::safe_ptr<ifaddrs, freeifaddrs>;
using xcb_connect_t = util::safe_ptr<xcb_connection_t, xcb_disconnect>;
using xcb_img_t = util::c_ptr<xcb_shm_get_image_reply_t>;
using xcb_img_t = util::c_ptr<xcb_shm_get_image_reply_t>;
using xdisplay_t = util::safe_ptr_v2<Display, int, XCloseDisplay>;
using ximg_t = util::safe_ptr<XImage, freeImage>;
using xcursor_t = util::safe_ptr<XFixesCursorImage, freeX>;
using ximg_t = util::safe_ptr<XImage, freeImage>;
using xcursor_t = util::safe_ptr<XFixesCursorImage, freeX>;
using crtc_info_t = util::safe_ptr<_XRRCrtcInfo, XRRFreeCrtcInfo>;
using crtc_info_t = util::safe_ptr<_XRRCrtcInfo, XRRFreeCrtcInfo>;
using output_info_t = util::safe_ptr<_XRROutputInfo, XRRFreeOutputInfo>;
using screen_res_t = util::safe_ptr<_XRRScreenResources, XRRFreeScreenResources>;
using screen_res_t = util::safe_ptr<_XRRScreenResources, XRRFreeScreenResources>;
class shm_id_t {
public:
@ -55,7 +54,7 @@ public:
}
~shm_id_t() {
if (id != -1) {
if(id != -1) {
shmctl(id, IPC_RMID, nullptr);
id = -1;
}
@ -65,15 +64,15 @@ public:
class shm_data_t {
public:
shm_data_t() : data { (void*) -1 } {}
shm_data_t() : data { (void *)-1 } {}
shm_data_t(void *data) : data { data } {}
shm_data_t(shm_data_t &&other) noexcept : data(other.data) {
other.data = (void*)-1;
other.data = (void *)-1;
}
~shm_data_t() {
if((std::uintptr_t) data != -1) {
if((std::uintptr_t)data != -1) {
shmdt(data);
}
}
@ -81,11 +80,11 @@ public:
void *data;
};
struct x11_img_t: public img_t {
struct x11_img_t : public img_t {
ximg_t img;
};
struct shm_img_t: public img_t {
struct shm_img_t : public img_t {
~shm_img_t() override {
delete[] data;
data = nullptr;
@ -95,7 +94,7 @@ struct shm_img_t: public img_t {
void blend_cursor(Display *display, img_t &img, int offsetX, int offsetY) {
xcursor_t overlay { XFixesGetCursorImage(display) };
if (!overlay) {
if(!overlay) {
BOOST_LOG(error) << "Couldn't get cursor from XFixesGetCursorImage"sv;
return;
}
@ -109,40 +108,39 @@ void blend_cursor(Display *display, img_t &img, int offsetX, int offsetY) {
overlay->x = std::max((short)0, overlay->x);
overlay->y = std::max((short)0, overlay->y);
auto pixels = (int*)img.data;
auto pixels = (int *)img.data;
auto screen_height = img.height;
auto screen_width = img.width;
auto screen_width = img.width;
auto delta_height = std::min<uint16_t>(overlay->height,std::max(0, screen_height - overlay->y));
auto delta_width = std::min<uint16_t>(overlay->width,std::max(0, screen_width - overlay->x));
for (auto y = 0; y < delta_height; ++y) {
auto delta_height = std::min<uint16_t>(overlay->height, std::max(0, screen_height - overlay->y));
auto delta_width = std::min<uint16_t>(overlay->width, std::max(0, screen_width - overlay->x));
for(auto y = 0; y < delta_height; ++y) {
auto overlay_begin = &overlay->pixels[y * overlay->width];
auto overlay_end = &overlay->pixels[y * overlay->width + delta_width];
auto overlay_end = &overlay->pixels[y * overlay->width + delta_width];
auto pixels_begin = &pixels[(y + overlay->y)* (img.row_pitch / img.pixel_pitch) + overlay->x];
auto pixels_begin = &pixels[(y + overlay->y) * (img.row_pitch / img.pixel_pitch) + overlay->x];
std::for_each(overlay_begin, overlay_end,[&](long pixel) {
int *pixel_p = (int*) &pixel;
std::for_each(overlay_begin, overlay_end, [&](long pixel) {
int *pixel_p = (int *)&pixel;
auto colors_in = (uint8_t*) pixels_begin;
auto colors_in = (uint8_t *)pixels_begin;
auto alpha = (*(uint*) pixel_p) >> 24u;
if (alpha == 255) {
auto alpha = (*(uint *)pixel_p) >> 24u;
if(alpha == 255) {
*pixels_begin = *pixel_p;
}
else {
auto colors_out = (uint8_t*) pixel_p;
colors_in[0] = colors_out[0] + (colors_in[0] * (255 - alpha) +255 /2) / 255;
colors_in[1] = colors_out[1] + (colors_in[1] * (255 - alpha) + 255 / 2) / 255;
colors_in[2] = colors_out[2] + (colors_in[2] * (255 - alpha) + 255 / 2) / 255;
auto colors_out = (uint8_t *)pixel_p;
colors_in[0] = colors_out[0] + (colors_in[0] * (255 - alpha) + 255 / 2) / 255;
colors_in[1] = colors_out[1] + (colors_in[1] * (255 - alpha) + 255 / 2) / 255;
colors_in[2] = colors_out[2] + (colors_in[2] * (255 - alpha) + 255 / 2) / 255;
}
++pixels_begin;
});
}
}
struct x11_attr_t: public display_t
{
struct x11_attr_t : public display_t {
xdisplay_t xdisplay;
Window xwindow;
XWindowAttributes xattr;
@ -153,7 +151,7 @@ struct x11_attr_t: public display_t
*/
int lastWidth, lastHeight;
x11_attr_t() : xdisplay { XOpenDisplay(nullptr) }, xwindow { }, xattr { } {
x11_attr_t() : xdisplay { XOpenDisplay(nullptr) }, xwindow {}, xattr {} {
XInitThreads();
}
@ -192,17 +190,17 @@ struct x11_attr_t: public display_t
BOOST_LOG(info)
<< "Streaming display: "sv << out_info->name << " with res "sv << crt_info->width << 'x' << crt_info->height << " offset by "sv << crt_info->x << 'x' << crt_info->y;
width = crt_info->width;
height = crt_info->height;
width = crt_info->width;
height = crt_info->height;
offset_x = crt_info->x;
offset_y = crt_info->y;
}
else {
width = xattr.width;
width = xattr.width;
height = xattr.height;
}
lastWidth = xattr.width;
lastWidth = xattr.width;
lastHeight = xattr.height;
return 0;
@ -219,21 +217,21 @@ struct x11_attr_t: public display_t
refresh();
//The whole X server changed, so we gotta reinit everything
if (xattr.width != lastWidth || xattr.height != lastHeight) {
BOOST_LOG(warning)<< "X dimensions changed in non-SHM mode, request reinit"sv;
if(xattr.width != lastWidth || xattr.height != lastHeight) {
BOOST_LOG(warning) << "X dimensions changed in non-SHM mode, request reinit"sv;
return capture_e::reinit;
}
XImage *img { XGetImage(xdisplay.get(), xwindow, offset_x, offset_y, width, height, AllPlanes, ZPixmap) };
auto img_out = (x11_img_t*) img_out_base;
img_out->width = img->width;
img_out->height = img->height;
img_out->data = (uint8_t*) img->data;
img_out->row_pitch = img->bytes_per_line;
auto img_out = (x11_img_t *)img_out_base;
img_out->width = img->width;
img_out->height = img->height;
img_out->data = (uint8_t *)img->data;
img_out->row_pitch = img->bytes_per_line;
img_out->pixel_pitch = img->bits_per_pixel / 8;
img_out->img.reset(img);
if (cursor) {
if(cursor) {
blend_cursor(xdisplay.get(), *img_out_base, offset_x, offset_y);
}
@ -250,7 +248,7 @@ struct x11_attr_t: public display_t
}
};
struct shm_attr_t: public x11_attr_t {
struct shm_attr_t : public x11_attr_t {
xdisplay_t shm_xdisplay; // Prevent race condition with x11_attr_t::xdisplay
xcb_connect_t xcb;
xcb_screen_t *display;
@ -265,7 +263,7 @@ struct shm_attr_t: public x11_attr_t {
void delayed_refresh() {
refresh();
refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh,2s, this).task_id;
refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh, 2s, this).task_id;
}
shm_attr_t() : x11_attr_t(), shm_xdisplay { XOpenDisplay(nullptr) } {
@ -273,25 +271,26 @@ struct shm_attr_t: public x11_attr_t {
}
~shm_attr_t() override {
while(!task_pool.cancel(refresh_task_id));
while(!task_pool.cancel(refresh_task_id))
;
}
capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) override {
//The whole X server changed, so we gotta reinit everything
if(xattr.width != lastWidth || xattr.height != lastHeight) {
BOOST_LOG(warning)<< "X dimensions changed in SHM mode, request reinit"sv;
if(xattr.width != lastWidth || xattr.height != lastHeight) {
BOOST_LOG(warning) << "X dimensions changed in SHM mode, request reinit"sv;
return capture_e::reinit;
}
else {
auto img_cookie = xcb_shm_get_image_unchecked(xcb.get(), display->root, offset_x, offset_y, width, height, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP, seg, 0);
xcb_img_t img_reply { xcb_shm_get_image_reply(xcb.get(), img_cookie,nullptr) };
xcb_img_t img_reply { xcb_shm_get_image_reply(xcb.get(), img_cookie, nullptr) };
if(!img_reply) {
BOOST_LOG(error) << "Could not get image reply"sv;
return capture_e::reinit;
}
std::copy_n((std::uint8_t*)data.data, frame_size(), img->data);
std::copy_n((std::uint8_t *)data.data, frame_size(), img->data);
if(cursor) {
blend_cursor(shm_xdisplay.get(), *img, offset_x, offset_y);
@ -302,12 +301,12 @@ struct shm_attr_t: public x11_attr_t {
}
std::shared_ptr<img_t> alloc_img() override {
auto img = std::make_shared<shm_img_t>();
img->width = width;
img->height = height;
auto img = std::make_shared<shm_img_t>();
img->width = width;
img->height = height;
img->pixel_pitch = 4;
img->row_pitch = img->pixel_pitch * width;
img->data = new std::uint8_t[height * img->row_pitch];
img->row_pitch = img->pixel_pitch * width;
img->data = new std::uint8_t[height * img->row_pitch];
return img;
}
@ -334,8 +333,8 @@ struct shm_attr_t: public x11_attr_t {
}
auto iter = xcb_setup_roots_iterator(xcb_get_setup(xcb.get()));
display = iter.data;
seg = xcb_generate_id(xcb.get());
display = iter.data;
seg = xcb_generate_id(xcb.get());
shm_id.id = shmget(IPC_PRIVATE, frame_size(), IPC_CREAT | 0777);
if(shm_id.id == -1) {
@ -360,19 +359,19 @@ struct shm_attr_t: public x11_attr_t {
}
};
struct mic_attr_t: public mic_t {
struct mic_attr_t : public mic_t {
pa_sample_spec ss;
util::safe_ptr<pa_simple, pa_simple_free> mic;
explicit mic_attr_t(pa_sample_format format, std::uint32_t sample_rate,
std::uint8_t channels) : ss { format, sample_rate, channels }, mic { } { }
std::uint8_t channels) : ss { format, sample_rate, channels }, mic {} {}
capture_e sample(std::vector<std::int16_t> &sample_buf) override {
auto sample_size = sample_buf.size();
auto buf = sample_buf.data();
int status;
if(pa_simple_read(mic.get(), buf, sample_size *2, &status)) {
if(pa_simple_read(mic.get(), buf, sample_size * 2, &status)) {
BOOST_LOG(error) << "pa_simple_read() failed: "sv << pa_strerror(status);
return capture_e::error;
@ -384,7 +383,7 @@ struct mic_attr_t: public mic_t {
std::shared_ptr<display_t> display(platf::dev_type_e hwdevice_type) {
if(hwdevice_type != platf::dev_type_e::none) {
BOOST_LOG(error)<< "Could not initialize display with the given hw device type."sv;
BOOST_LOG(error) << "Could not initialize display with the given hw device type."sv;
return nullptr;
}
@ -416,16 +415,16 @@ std::unique_ptr<mic_t> microphone(std::uint32_t sample_rate, std::uint32_t) {
int status;
const char *audio_sink = "@DEFAULT_MONITOR@";
if (!config::audio.sink.empty()) {
if(!config::audio.sink.empty()) {
audio_sink = config::audio.sink.c_str();
}
mic->mic.reset(
pa_simple_new(nullptr, "sunshine",
pa_stream_direction_t::PA_STREAM_RECORD, audio_sink,
pa_stream_direction_t::PA_STREAM_RECORD, audio_sink,
"sunshine-record", &mic->ss, nullptr, nullptr, &status));
if (!mic->mic) {
if(!mic->mic) {
auto err_str = pa_strerror(status);
BOOST_LOG(error) << "pa_simple_new() failed: "sv << err_str;
@ -448,14 +447,14 @@ std::string from_sockaddr(const sockaddr *const ip_addr) {
char data[INET6_ADDRSTRLEN];
auto family = ip_addr->sa_family;
if (family == AF_INET6) {
inet_ntop(AF_INET6, &((sockaddr_in6*) ip_addr)->sin6_addr, data,
INET6_ADDRSTRLEN);
if(family == AF_INET6) {
inet_ntop(AF_INET6, &((sockaddr_in6 *)ip_addr)->sin6_addr, data,
INET6_ADDRSTRLEN);
}
if (family == AF_INET) {
inet_ntop(AF_INET, &((sockaddr_in*) ip_addr)->sin_addr, data,
INET_ADDRSTRLEN);
if(family == AF_INET) {
inet_ntop(AF_INET, &((sockaddr_in *)ip_addr)->sin_addr, data,
INET_ADDRSTRLEN);
}
return std::string { data };
@ -467,26 +466,26 @@ std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_
auto family = ip_addr->sa_family;
std::uint16_t port;
if(family == AF_INET6) {
inet_ntop(AF_INET6, &((sockaddr_in6*)ip_addr)->sin6_addr, data,
INET6_ADDRSTRLEN);
port = ((sockaddr_in6*) ip_addr)->sin6_port;
inet_ntop(AF_INET6, &((sockaddr_in6 *)ip_addr)->sin6_addr, data,
INET6_ADDRSTRLEN);
port = ((sockaddr_in6 *)ip_addr)->sin6_port;
}
if(family == AF_INET) {
inet_ntop(AF_INET, &((sockaddr_in*)ip_addr)->sin_addr, data,
INET_ADDRSTRLEN);
port = ((sockaddr_in*) ip_addr)->sin_port;
inet_ntop(AF_INET, &((sockaddr_in *)ip_addr)->sin_addr, data,
INET_ADDRSTRLEN);
port = ((sockaddr_in *)ip_addr)->sin_port;
}
return { port, std::string {data} };
return { port, std::string { data } };
}
std::string get_mac_address(const std::string_view &address) {
auto ifaddrs = get_ifaddrs();
for (auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next) {
if (pos->ifa_addr && address == from_sockaddr(pos->ifa_addr)) {
for(auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next) {
if(pos->ifa_addr && address == from_sockaddr(pos->ifa_addr)) {
std::ifstream mac_file("/sys/class/net/"s + pos->ifa_name + "/address");
if (mac_file.good()) {
if(mac_file.good()) {
std::string mac_address;
std::getline(mac_file, mac_address);
return mac_address;
@ -504,4 +503,4 @@ void freeImage(XImage *p) {
void freeX(XFixesCursorImage *p) {
XFree(p);
}
}
} // namespace platf

View file

@ -1,5 +1,5 @@
#include <libevdev/libevdev.h>
#include <libevdev/libevdev-uinput.h>
#include <libevdev/libevdev.h>
#include <X11/X.h>
#include <X11/Xlib.h>
@ -10,8 +10,8 @@
#include <cstring>
#include <filesystem>
#include "sunshine/platform/common.h"
#include "sunshine/main.h"
#include "sunshine/platform/common.h"
#include "sunshine/utility.h"
// Support older versions
@ -25,7 +25,7 @@
namespace platf {
using namespace std::literals;
using evdev_t = util::safe_ptr<libevdev, libevdev_free>;
using evdev_t = util::safe_ptr<libevdev, libevdev_free>;
using uinput_t = util::safe_ptr<libevdev_uinput, libevdev_uinput_destroy>;
using keyboard_t = util::safe_ptr_v2<Display, int, XCloseDisplay>;
@ -66,7 +66,7 @@ public:
std::filesystem::remove(gamepad_path);
}
gamepads[nr] = std::make_pair(uinput_t{}, gamepad_state_t {});
gamepads[nr] = std::make_pair(uinput_t {}, gamepad_state_t {});
}
int create_mouse() {
@ -143,7 +143,7 @@ public:
};
void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {
auto touchscreen = ((input_raw_t*)input.get())->touch_input.get();
auto touchscreen = ((input_raw_t *)input.get())->touch_input.get();
auto scaled_x = (int)std::lround((x + touch_port.offset_x) * ((float)target_touch_port.width / (float)touch_port.width));
auto scaled_y = (int)std::lround((y + touch_port.offset_y) * ((float)target_touch_port.height / (float)touch_port.height));
@ -157,7 +157,7 @@ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y)
}
void move_mouse(input_t &input, int deltaX, int deltaY) {
auto mouse = ((input_raw_t*)input.get())->mouse_input.get();
auto mouse = ((input_raw_t *)input.get())->mouse_input.get();
if(deltaX) {
libevdev_uinput_write_event(mouse, EV_REL, REL_X, deltaX);
@ -176,26 +176,26 @@ void button_mouse(input_t &input, int button, bool release) {
if(button == 1) {
btn_type = BTN_LEFT;
scan = 90001;
scan = 90001;
}
else if(button == 2) {
btn_type = BTN_MIDDLE;
scan = 90003;
scan = 90003;
}
else if(button == 3) {
btn_type = BTN_RIGHT;
scan = 90002;
scan = 90002;
}
else if(button == 4) {
btn_type = BTN_SIDE;
scan = 90004;
scan = 90004;
}
else {
btn_type = BTN_EXTRA;
scan = 90005;
scan = 90005;
}
auto mouse = ((input_raw_t*)input.get())->mouse_input.get();
auto mouse = ((input_raw_t *)input.get())->mouse_input.get();
libevdev_uinput_write_event(mouse, EV_MSC, MSC_SCAN, scan);
libevdev_uinput_write_event(mouse, EV_KEY, btn_type, release ? 0 : 1);
libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0);
@ -204,7 +204,7 @@ void button_mouse(input_t &input, int button, bool release) {
void scroll(input_t &input, int high_res_distance) {
int distance = high_res_distance / 120;
auto mouse = ((input_raw_t*)input.get())->mouse_input.get();
auto mouse = ((input_raw_t *)input.get())->mouse_input.get();
libevdev_uinput_write_event(mouse, EV_REL, REL_WHEEL, distance);
libevdev_uinput_write_event(mouse, EV_REL, REL_WHEEL_HI_RES, high_res_distance);
libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0);
@ -212,7 +212,7 @@ void scroll(input_t &input, int high_res_distance) {
uint16_t keysym(uint16_t modcode) {
constexpr auto VK_NUMPAD = 0x60;
constexpr auto VK_F1 = 0x70;
constexpr auto VK_F1 = 0x70;
if(modcode >= VK_NUMPAD && modcode < VK_NUMPAD + 10) {
return XK_KP_0 + (modcode - VK_NUMPAD);
@ -224,108 +224,108 @@ uint16_t keysym(uint16_t modcode) {
switch(modcode) {
case 0x08:
return XK_BackSpace;
case 0x09:
return XK_Tab;
case 0x0D:
return XK_Return;
case 0x13:
return XK_Pause;
case 0x14:
return XK_Caps_Lock;
case 0x1B:
return XK_Escape;
case 0x21:
return XK_Page_Up;
case 0x22:
return XK_Page_Down;
case 0x23:
return XK_End;
case 0x24:
return XK_Home;
case 0x25:
return XK_Left;
case 0x26:
return XK_Up;
case 0x27:
return XK_Right;
case 0x28:
return XK_Down;
case 0x29:
return XK_Select;
case 0x2B:
return XK_Execute;
case 0x2C:
return XK_Print;
case 0x2D:
return XK_Insert;
case 0x2E:
return XK_Delete;
case 0x2F:
return XK_Help;
case 0x6A:
return XK_KP_Multiply;
case 0x6B:
return XK_KP_Add;
case 0x6C:
return XK_KP_Separator;
case 0x6D:
return XK_KP_Subtract;
case 0x6E:
return XK_KP_Decimal;
case 0x6F:
return XK_KP_Divide;
case 0x90:
return XK_Num_Lock;
case 0x91:
return XK_Scroll_Lock;
case 0xA0:
return XK_Shift_L;
case 0xA1:
return XK_Shift_R;
case 0xA2:
return XK_Control_L;
case 0xA3:
return XK_Control_R;
case 0xA4:
return XK_Alt_L;
case 0xA5: /* return XK_Alt_R; */
return XK_Super_L;
case 0x5B:
return XK_Super_L;
case 0x5C:
return XK_Super_R;
case 0xBA:
return XK_semicolon;
case 0xBB:
return XK_equal;
case 0xBC:
return XK_comma;
case 0xBD:
return XK_minus;
case 0xBE:
return XK_period;
case 0xBF:
return XK_slash;
case 0xC0:
return XK_grave;
case 0xDB:
return XK_bracketleft;
case 0xDC:
return XK_backslash;
case 0xDD:
return XK_bracketright;
case 0xDE:
return XK_apostrophe;
case 0x08:
return XK_BackSpace;
case 0x09:
return XK_Tab;
case 0x0D:
return XK_Return;
case 0x13:
return XK_Pause;
case 0x14:
return XK_Caps_Lock;
case 0x1B:
return XK_Escape;
case 0x21:
return XK_Page_Up;
case 0x22:
return XK_Page_Down;
case 0x23:
return XK_End;
case 0x24:
return XK_Home;
case 0x25:
return XK_Left;
case 0x26:
return XK_Up;
case 0x27:
return XK_Right;
case 0x28:
return XK_Down;
case 0x29:
return XK_Select;
case 0x2B:
return XK_Execute;
case 0x2C:
return XK_Print;
case 0x2D:
return XK_Insert;
case 0x2E:
return XK_Delete;
case 0x2F:
return XK_Help;
case 0x6A:
return XK_KP_Multiply;
case 0x6B:
return XK_KP_Add;
case 0x6C:
return XK_KP_Separator;
case 0x6D:
return XK_KP_Subtract;
case 0x6E:
return XK_KP_Decimal;
case 0x6F:
return XK_KP_Divide;
case 0x90:
return XK_Num_Lock;
case 0x91:
return XK_Scroll_Lock;
case 0xA0:
return XK_Shift_L;
case 0xA1:
return XK_Shift_R;
case 0xA2:
return XK_Control_L;
case 0xA3:
return XK_Control_R;
case 0xA4:
return XK_Alt_L;
case 0xA5: /* return XK_Alt_R; */
return XK_Super_L;
case 0x5B:
return XK_Super_L;
case 0x5C:
return XK_Super_R;
case 0xBA:
return XK_semicolon;
case 0xBB:
return XK_equal;
case 0xBC:
return XK_comma;
case 0xBD:
return XK_minus;
case 0xBE:
return XK_period;
case 0xBF:
return XK_slash;
case 0xC0:
return XK_grave;
case 0xDB:
return XK_bracketleft;
case 0xDC:
return XK_backslash;
case 0xDD:
return XK_bracketright;
case 0xDE:
return XK_apostrophe;
}
return modcode;
}
void keyboard(input_t &input, uint16_t modcode, bool release) {
auto &keyboard = ((input_raw_t*)input.get())->keyboard;
KeyCode kc = XKeysymToKeycode(keyboard.get(), keysym(modcode));
auto &keyboard = ((input_raw_t *)input.get())->keyboard;
KeyCode kc = XKeysymToKeycode(keyboard.get(), keysym(modcode));
if(!kc) {
return;
@ -338,18 +338,18 @@ void keyboard(input_t &input, uint16_t modcode, bool release) {
}
int alloc_gamepad(input_t &input, int nr) {
return ((input_raw_t*)input.get())->alloc_gamepad(nr);
return ((input_raw_t *)input.get())->alloc_gamepad(nr);
}
void free_gamepad(input_t &input, int nr) {
((input_raw_t*)input.get())->clear_gamepad(nr);
((input_raw_t *)input.get())->clear_gamepad(nr);
}
void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) {
TUPLE_2D_REF(uinput, gamepad_state_old, ((input_raw_t*)input.get())->gamepads[nr]);
TUPLE_2D_REF(uinput, gamepad_state_old, ((input_raw_t *)input.get())->gamepads[nr]);
auto bf = gamepad_state.buttonFlags ^ gamepad_state_old.buttonFlags;
auto bf = gamepad_state.buttonFlags ^ gamepad_state_old.buttonFlags;
auto bf_new = gamepad_state.buttonFlags;
if(bf) {
@ -366,17 +366,17 @@ void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) {
libevdev_uinput_write_event(uinput.get(), EV_ABS, ABS_HAT0X, button_state);
}
if(START & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_START, bf_new & START ? 1 : 0);
if(BACK & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_SELECT, bf_new & BACK ? 1 : 0);
if(LEFT_STICK & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_THUMBL, bf_new & LEFT_STICK ? 1 : 0);
if(RIGHT_STICK & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_THUMBR, bf_new & RIGHT_STICK ? 1 : 0);
if(LEFT_BUTTON & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_TL, bf_new & LEFT_BUTTON ? 1 : 0);
if(RIGHT_BUTTON & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_TR, bf_new & RIGHT_BUTTON ? 1 : 0);
if(HOME & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_MODE, bf_new & HOME ? 1 : 0);
if(A & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_SOUTH, bf_new & A ? 1 : 0);
if(B & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_EAST, bf_new & B ? 1 : 0);
if(X & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_NORTH, bf_new & X ? 1 : 0);
if(Y & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_WEST, bf_new & Y ? 1 : 0);
if(START & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_START, bf_new & START ? 1 : 0);
if(BACK & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_SELECT, bf_new & BACK ? 1 : 0);
if(LEFT_STICK & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_THUMBL, bf_new & LEFT_STICK ? 1 : 0);
if(RIGHT_STICK & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_THUMBR, bf_new & RIGHT_STICK ? 1 : 0);
if(LEFT_BUTTON & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_TL, bf_new & LEFT_BUTTON ? 1 : 0);
if(RIGHT_BUTTON & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_TR, bf_new & RIGHT_BUTTON ? 1 : 0);
if(HOME & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_MODE, bf_new & HOME ? 1 : 0);
if(A & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_SOUTH, bf_new & A ? 1 : 0);
if(B & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_EAST, bf_new & B ? 1 : 0);
if(X & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_NORTH, bf_new & X ? 1 : 0);
if(Y & bf) libevdev_uinput_write_event(uinput.get(), EV_KEY, BTN_WEST, bf_new & Y ? 1 : 0);
}
if(gamepad_state_old.lt != gamepad_state.lt) {
@ -408,7 +408,7 @@ void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) {
}
evdev_t mouse() {
evdev_t dev { libevdev_new() };
evdev_t dev { libevdev_new() };
libevdev_set_uniq(dev.get(), "Sunshine Mouse");
libevdev_set_id_product(dev.get(), 0x4038);
@ -553,7 +553,7 @@ evdev_t x360() {
input_t input() {
input_t result { new input_raw_t() };
auto &gp = *(input_raw_t*)result.get();
auto &gp = *(input_raw_t *)result.get();
gp.keyboard.reset(XOpenDisplay(nullptr));
@ -568,8 +568,8 @@ input_t input() {
// Ensure starting from clean slate
gp.clear();
gp.touch_dev = touchscreen();
gp.mouse_dev = mouse();
gp.touch_dev = touchscreen();
gp.mouse_dev = mouse();
gp.gamepad_dev = x360();
if(gp.create_mouse() || gp.create_touchscreen()) {
@ -581,9 +581,9 @@ input_t input() {
}
void freeInput(void *p) {
auto *input = (input_raw_t*)p;
auto *input = (input_raw_t *)p;
delete input;
}
std::unique_ptr<deinit_t> init() { return std::make_unique<deinit_t>(); }
}
} // namespace platf

View file

@ -2,9 +2,9 @@
// Created by loki on 1/12/20.
//
#include <roapi.h>
#include <mmdeviceapi.h>
#include <audioclient.h>
#include <mmdeviceapi.h>
#include <roapi.h>
#include <codecvt>
@ -36,7 +36,7 @@ using device_t = util::safe_ptr<IMMDevice, Release<IMMDevice>>;
using audio_client_t = util::safe_ptr<IAudioClient, Release<IAudioClient>>;
using audio_capture_t = util::safe_ptr<IAudioCaptureClient, Release<IAudioCaptureClient>>;
using wave_format_t = util::safe_ptr<WAVEFORMATEX, co_task_free<WAVEFORMATEX>>;
using handle_t = util::safe_ptr_v2<void, BOOL, CloseHandle>;
using handle_t = util::safe_ptr_v2<void, BOOL, CloseHandle>;
class co_init_t : public deinit_t {
public:
@ -53,32 +53,26 @@ struct format_t {
std::string_view name;
int channels;
int channel_mask;
} formats [] {
{
"Stereo"sv,
} formats[] {
{ "Stereo"sv,
2,
SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT
},
{
"Mono"sv,
SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT },
{ "Mono"sv,
1,
SPEAKER_FRONT_CENTER
},
{
"Surround 5.1"sv,
SPEAKER_FRONT_CENTER },
{ "Surround 5.1"sv,
6,
SPEAKER_FRONT_LEFT |
SPEAKER_FRONT_RIGHT |
SPEAKER_FRONT_CENTER |
SPEAKER_LOW_FREQUENCY |
SPEAKER_BACK_LEFT |
SPEAKER_BACK_RIGHT
}
SPEAKER_FRONT_LEFT |
SPEAKER_FRONT_RIGHT |
SPEAKER_FRONT_CENTER |
SPEAKER_LOW_FREQUENCY |
SPEAKER_BACK_LEFT |
SPEAKER_BACK_RIGHT }
};
void set_wave_format(audio::wave_format_t &wave_format, const format_t &format) {
wave_format->nChannels = format.channels;
wave_format->nBlockAlign = wave_format->nChannels * wave_format->wBitsPerSample / 8;
wave_format->nChannels = format.channels;
wave_format->nBlockAlign = wave_format->nChannels * wave_format->wBitsPerSample / 8;
wave_format->nAvgBytesPerSec = wave_format->nSamplesPerSec * wave_format->nBlockAlign;
if(wave_format->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
@ -97,8 +91,8 @@ void surround51_to_stereo(std::vector<std::int16_t> &sample_in, const util::buff
channels51 // number of channels in surround sound
};
auto sample_in_pos = std::begin(sample_in);
auto sample_end = std::begin(sample_out) + sample_in.size() / 2 * channels51;
auto sample_in_pos = std::begin(sample_in);
auto sample_end = std::begin(sample_out) + sample_in.size() / 2 * channels51;
for(auto sample_out_p = std::begin(sample_out); sample_out_p != sample_end; sample_out_p += channels51) {
std::uint32_t left {}, right {};
@ -113,7 +107,8 @@ void surround51_to_stereo(std::vector<std::int16_t> &sample_in, const util::buff
right += sample_out_p[front_center] * 90 / 100;
right += sample_out_p[low_frequency] * 30 / 100;
right += sample_out_p[back_left] * 30 / 100;
right += sample_out_p[back_right] * 70 / 100;;
right += sample_out_p[back_right] * 70 / 100;
;
*sample_in_pos++ = (std::uint16_t)left;
*sample_in_pos++ = (std::uint16_t)right;
@ -121,8 +116,8 @@ void surround51_to_stereo(std::vector<std::int16_t> &sample_in, const util::buff
}
void mono_to_stereo(std::vector<std::int16_t> &sample_in, const util::buffer_t<std::int16_t> &sample_out) {
auto sample_in_pos = std::begin(sample_in);
auto sample_end = std::begin(sample_out) + sample_in.size() / 2;
auto sample_in_pos = std::begin(sample_in);
auto sample_end = std::begin(sample_out) + sample_in.size() / 2;
for(auto sample_out_p = std::begin(sample_out); sample_out_p != sample_end; ++sample_out_p) {
*sample_in_pos++ = *sample_out_p;
@ -156,23 +151,23 @@ audio_client_t make_audio_client(device_t &device, const format_t &format, int s
wave_format->wBitsPerSample = 16;
wave_format->nSamplesPerSec = sample_rate;
switch(wave_format->wFormatTag) {
case WAVE_FORMAT_PCM:
case WAVE_FORMAT_PCM:
break;
case WAVE_FORMAT_IEEE_FLOAT:
break;
case WAVE_FORMAT_EXTENSIBLE: {
auto wave_ex = (PWAVEFORMATEXTENSIBLE)wave_format.get();
if(IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, wave_ex->SubFormat)) {
wave_ex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
wave_ex->Samples.wValidBitsPerSample = 16;
break;
case WAVE_FORMAT_IEEE_FLOAT:
break;
case WAVE_FORMAT_EXTENSIBLE: {
auto wave_ex = (PWAVEFORMATEXTENSIBLE) wave_format.get();
if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, wave_ex->SubFormat)) {
wave_ex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
wave_ex->Samples.wValidBitsPerSample = 16;
break;
}
BOOST_LOG(error) << "Unsupported Sub Format for WAVE_FORMAT_EXTENSIBLE: [0x"sv << util::hex(wave_ex->SubFormat).to_string_view() << ']';
}
default:
BOOST_LOG(error) << "Unsupported Wave Format: [0x"sv << util::hex(wave_format->wFormatTag).to_string_view() << ']';
return nullptr;
BOOST_LOG(error) << "Unsupported Sub Format for WAVE_FORMAT_EXTENSIBLE: [0x"sv << util::hex(wave_ex->SubFormat).to_string_view() << ']';
}
default:
BOOST_LOG(error) << "Unsupported Wave Format: [0x"sv << util::hex(wave_format->wFormatTag).to_string_view() << ']';
return nullptr;
};
set_wave_format(wave_format, format);
@ -195,7 +190,7 @@ audio_client_t make_audio_client(device_t &device, const format_t &format, int s
class mic_wasapi_t : public mic_t {
public:
capture_e sample(std::vector<std::int16_t> &sample_in) override {
auto sample_size = sample_in.size() /2 * format->channels;
auto sample_size = sample_in.size() / 2 * format->channels;
while(sample_buf_pos - std::begin(sample_buf) < sample_size) {
//FIXME: Use IAudioClient3 instead of IAudioClient, that would allows for adjusting the latency of the audio samples
auto capture_result = _fill_buffer();
@ -243,7 +238,7 @@ public:
nullptr,
CLSCTX_ALL,
IID_IMMDeviceEnumerator,
(void **) &device_enum);
(void **)&device_enum);
if(FAILED(status)) {
BOOST_LOG(error) << "Couldn't create Device Enumerator [0x"sv << util::hex(status).to_string_view() << ']';
@ -292,32 +287,32 @@ public:
std::uint32_t frames;
status = audio_client->GetBufferSize(&frames);
if (FAILED(status)) {
if(FAILED(status)) {
BOOST_LOG(error) << "Couldn't acquire the number of audio frames [0x"sv << util::hex(status).to_string_view() << ']';
return -1;
}
// *2 --> needs to fit double
sample_buf = util::buffer_t<std::int16_t> { std::max(frames *2, frame_size * format->channels *2) };
sample_buf = util::buffer_t<std::int16_t> { std::max(frames * 2, frame_size * format->channels * 2) };
sample_buf_pos = std::begin(sample_buf);
status = audio_client->GetService(IID_IAudioCaptureClient, (void**)&audio_capture);
if (FAILED(status)) {
status = audio_client->GetService(IID_IAudioCaptureClient, (void **)&audio_capture);
if(FAILED(status)) {
BOOST_LOG(error) << "Couldn't initialize audio capture client [0x"sv << util::hex(status).to_string_view() << ']';
return -1;
}
status = audio_client->SetEventHandle(audio_event.get());
if (FAILED(status)) {
if(FAILED(status)) {
BOOST_LOG(error) << "Couldn't set event handle [0x"sv << util::hex(status).to_string_view() << ']';
return -1;
}
status = audio_client->Start();
if (FAILED(status)) {
if(FAILED(status)) {
BOOST_LOG(error) << "Couldn't start recording [0x"sv << util::hex(status).to_string_view() << ']';
return -1;
@ -331,6 +326,7 @@ public:
audio_client->Stop();
}
}
private:
capture_e _fill_buffer() {
HRESULT status;
@ -347,45 +343,45 @@ private:
} block_aligned;
status = WaitForSingleObjectEx(audio_event.get(), default_latency_ms, FALSE);
switch (status) {
case WAIT_OBJECT_0:
break;
case WAIT_TIMEOUT:
return capture_e::timeout;
default:
BOOST_LOG(error) << "Couldn't wait for audio event: [0x"sv << util::hex(status).to_string_view() << ']';
return capture_e::error;
switch(status) {
case WAIT_OBJECT_0:
break;
case WAIT_TIMEOUT:
return capture_e::timeout;
default:
BOOST_LOG(error) << "Couldn't wait for audio event: [0x"sv << util::hex(status).to_string_view() << ']';
return capture_e::error;
}
std::uint32_t packet_size{};
for (
std::uint32_t packet_size {};
for(
status = audio_capture->GetNextPacketSize(&packet_size);
SUCCEEDED(status) && packet_size > 0;
status = audio_capture->GetNextPacketSize(&packet_size)
) {
status = audio_capture->GetNextPacketSize(&packet_size)) {
DWORD buffer_flags;
status = audio_capture->GetBuffer(
(BYTE **) &sample_aligned.samples,
(BYTE **)&sample_aligned.samples,
&block_aligned.audio_sample_size,
&buffer_flags,
nullptr, nullptr);
switch (status) {
case S_OK:
break;
case AUDCLNT_E_DEVICE_INVALIDATED:
return capture_e::reinit;
default:
BOOST_LOG(error) << "Couldn't capture audio [0x"sv << util::hex(status).to_string_view() << ']';
return capture_e::error;
switch(status) {
case S_OK:
break;
case AUDCLNT_E_DEVICE_INVALIDATED:
return capture_e::reinit;
default:
BOOST_LOG(error) << "Couldn't capture audio [0x"sv << util::hex(status).to_string_view() << ']';
return capture_e::error;
}
sample_aligned.uninitialized = std::end(sample_buf) - sample_buf_pos;
auto n = std::min(sample_aligned.uninitialized, block_aligned.audio_sample_size * format->channels);
auto n = std::min(sample_aligned.uninitialized, block_aligned.audio_sample_size * format->channels);
if (buffer_flags & AUDCLNT_BUFFERFLAGS_SILENT) {
if(buffer_flags & AUDCLNT_BUFFERFLAGS_SILENT) {
std::fill_n(sample_buf_pos, n, 0);
} else {
}
else {
std::copy_n(sample_aligned.samples, n, sample_buf_pos);
}
@ -394,16 +390,17 @@ private:
audio_capture->ReleaseBuffer(block_aligned.audio_sample_size);
}
if (status == AUDCLNT_E_DEVICE_INVALIDATED) {
if(status == AUDCLNT_E_DEVICE_INVALIDATED) {
return capture_e::reinit;
}
if (FAILED(status)) {
if(FAILED(status)) {
return capture_e::error;
}
return capture_e::ok;
}
public:
handle_t audio_event;
@ -419,7 +416,7 @@ public:
format_t *format;
};
}
} // namespace platf::audio
namespace platf {
@ -444,4 +441,4 @@ std::unique_ptr<deinit_t> init() {
}
return std::make_unique<platf::audio::co_init_t>();
}
}
} // namespace platf

Some files were not shown because too many files have changed in this diff Show more