docs(doxygen): enforce warn if undocumented (#5337)

This commit is contained in:
Dave Lane
2026-06-25 22:43:17 -04:00
committed by GitHub
parent be7c1bcdfb
commit a991a9622c
141 changed files with 11804 additions and 1524 deletions

View File

@@ -45,10 +45,19 @@ namespace nvhttp {
namespace fs = std::filesystem;
namespace pt = boost::property_tree;
crypto::cert_chain_t cert_chain;
crypto::cert_chain_t cert_chain; ///< Certificate chain presented by Sunshine's GameStream HTTPS server.
/**
* @brief HTTPS server backend that adds Sunshine's client-certificate verification.
*/
class SunshineHTTPSServer: public SimpleWeb::ServerBase<SunshineHTTPS> {
public:
/**
* @brief Initialize the HTTPS server with Sunshine's certificate and key files.
*
* @param certification_file Path to the server certificate file.
* @param private_key_file Path to the matching private key file.
*/
SunshineHTTPSServer(const std::string &certification_file, const std::string &private_key_file):
ServerBase<SunshineHTTPS>::ServerBase(443),
context(boost::asio::ssl::context::tls_server) {
@@ -59,12 +68,15 @@ namespace nvhttp {
context.use_private_key_file(private_key_file, boost::asio::ssl::context::pem);
}
std::function<int(SSL *)> verify;
std::function<void(std::shared_ptr<Response>, std::shared_ptr<Request>)> on_verify_failed;
std::function<int(SSL *)> verify; ///< Callback that validates a client's TLS certificate after handshake.
std::function<void(std::shared_ptr<Response>, std::shared_ptr<Request>)> on_verify_failed; ///< Handler used to return the pairing challenge when client verification fails.
protected:
boost::asio::ssl::context context;
boost::asio::ssl::context context; ///< TLS server context configured with Sunshine's certificate and protocol policy.
/**
* @brief Enable client-certificate verification after the listening socket is bound.
*/
void after_bind() override {
if (verify) {
context.set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert | boost::asio::ssl::verify_client_once);
@@ -76,6 +88,9 @@ namespace nvhttp {
}
// This is Server<HTTPS>::accept() with SSL validation support added
/**
* @brief Accept a pending connection and arm the server for the next client.
*/
void accept() override {
auto connection = create_connection(*io_service, context);
@@ -120,44 +135,85 @@ namespace nvhttp {
}
};
/**
* @brief HTTPS server type used for GameStream endpoints requiring TLS.
*/
using https_server_t = SunshineHTTPSServer;
/**
* @brief Plain HTTP server type used for GameStream endpoints without TLS.
*/
using http_server_t = SimpleWeb::Server<SimpleWeb::HTTP>;
/**
* @brief Internal HTTPS credential paths for the configuration server.
*/
struct conf_intern_t {
std::string servercert;
std::string pkey;
} conf_intern;
std::string servercert; ///< Server certificate PEM string.
std::string pkey; ///< Private key PEM string or path.
} conf_intern; ///< TLS credential paths loaded from Sunshine's runtime configuration.
/**
* @brief Certificate entry associated with a client name and UUID.
*/
struct named_cert_t {
std::string name;
std::string uuid;
std::string cert;
bool enabled = true;
std::string name; ///< Human-readable name for this item.
std::string uuid; ///< Persistent Moonlight client UUID associated with the certificate.
std::string cert; ///< Certificate PEM string or path.
bool enabled = true; ///< Whether this persisted client entry may connect.
};
/**
* @brief Persisted pairing data for one Moonlight client.
*/
struct client_t {
std::vector<named_cert_t> named_devices;
std::vector<named_cert_t> named_devices; ///< Persisted Moonlight clients allowed to pair or reconnect.
};
// uniqueID, session
std::unordered_map<std::string, pair_session_t> map_id_sess;
client_t client_root;
std::atomic<uint32_t> session_id_counter;
std::unordered_map<std::string, pair_session_t> map_id_sess; ///< Pairing sessions keyed by temporary unique ID.
client_t client_root; ///< In-memory representation of the paired-client database.
std::atomic<uint32_t> session_id_counter; ///< Monotonic counter used to allocate GameStream session IDs.
// Set by TLS verify callback, read by launch/resume handler (single-threaded HTTPS server)
std::string last_verified_client_cert; // NOSONAR(cpp:S5421) - intentionally mutable global
std::string last_verified_client_cert; ///< Last client certificate accepted by the TLS verify callback. // NOSONAR(cpp:S5421) - intentionally mutable global
/**
* @brief Case-insensitive map used for HTTP headers and query parameters.
*/
using args_t = SimpleWeb::CaseInsensitiveMultimap;
/**
* @brief Shared HTTPS response object passed to GameStream handlers.
*/
using resp_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SunshineHTTPS>::Response>;
/**
* @brief Shared HTTPS request object received by GameStream handlers.
*/
using req_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SunshineHTTPS>::Request>;
/**
* @brief Shared HTTP response object passed to redirect and discovery handlers.
*/
using resp_http_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTP>::Response>;
/**
* @brief Shared HTTP request object received by redirect and discovery handlers.
*/
using req_http_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTP>::Request>;
/**
* @brief Certificate operations supported by the pairing API.
*/
enum class op_e {
ADD, ///< Add certificate
REMOVE ///< Remove certificate
};
/**
* @brief Read a named query argument from the HTTP request map.
*
* @param args Parsed query-string argument map.
* @param name Query parameter name to read.
* @param default_value Value returned when the parameter is absent.
* @return Query parameter value, default value, or an empty string.
*/
std::string get_arg(const args_t &args, const char *name, const char *default_value = nullptr) {
auto it = args.find(name);
if (it == std::end(args)) {
@@ -170,6 +226,9 @@ namespace nvhttp {
return it->second;
}
/**
* @brief Persist the current state to its backing store.
*/
void save_state() {
pt::ptree root;
@@ -207,6 +266,9 @@ namespace nvhttp {
}
}
/**
* @brief Load state from its backing store.
*/
void load_state() {
if (!fs::exists(config::nvhttp.file_state)) {
BOOST_LOG(info) << "File "sv << config::nvhttp.file_state << " doesn't exist"sv;
@@ -272,6 +334,12 @@ namespace nvhttp {
client_root = client;
}
/**
* @brief Add authorized client data.
*
* @param name Human-readable name to assign.
* @param cert Certificate data or object used by the operation.
*/
void add_authorized_client(const std::string &name, std::string &&cert) {
client_t &client = client_root;
named_cert_t named_cert;
@@ -285,6 +353,13 @@ namespace nvhttp {
}
}
/**
* @brief Create launch session.
*
* @param host_audio Host audio.
* @param args Arguments forwarded to the callable or parser.
* @return Constructed launch session object.
*/
std::shared_ptr<rtsp_stream::launch_session_t> make_launch_session(bool host_audio, const args_t &args) {
auto launch_session = std::make_shared<rtsp_stream::launch_session_t>();
@@ -348,6 +423,13 @@ namespace nvhttp {
map_id_sess.erase(sess.client.uniqueID);
}
/**
* @brief Return the GameStream pairing failure response.
*
* @param sess Pairing session that owns the request state.
* @param tree XML property tree used for the response body.
* @param status_msg Status msg.
*/
void fail_pair(pair_session_t &sess, pt::ptree &tree, const std::string status_msg) {
tree.put("root.paired", 0);
tree.put("root.<xmlattr>.status_code", 400);
@@ -355,6 +437,13 @@ namespace nvhttp {
remove_session(sess); // Security measure, delete the session when something went wrong and force a re-pair
}
/**
* @brief Return the server certificate text for pairing responses.
*
* @param sess Pairing session that owns the request state.
* @param tree XML property tree used for the response body.
* @param pin PIN supplied by the client during pairing.
*/
void getservercert(pair_session_t &sess, pt::ptree &tree, const std::string &pin) {
if (sess.last_phase != PAIR_PHASE::NONE) {
fail_pair(sess, tree, "Out of order call to getservercert");
@@ -379,6 +468,13 @@ namespace nvhttp {
tree.put("root.<xmlattr>.status_code", 200);
}
/**
* @brief Handle the client-challenge phase of GameStream pairing.
*
* @param sess Pairing session that owns the request state.
* @param tree XML property tree used for the response body.
* @param challenge Client challenge bytes from the pairing request.
*/
void clientchallenge(pair_session_t &sess, pt::ptree &tree, const std::string &challenge) {
if (sess.last_phase != PAIR_PHASE::GETSERVERCERT) {
fail_pair(sess, tree, "Out of order call to clientchallenge");
@@ -422,6 +518,13 @@ namespace nvhttp {
tree.put("root.<xmlattr>.status_code", 200);
}
/**
* @brief Handle the server-challenge response phase of GameStream pairing.
*
* @param sess Pairing session that owns the request state.
* @param tree XML property tree used for the response body.
* @param encrypted_response Encrypted response.
*/
void serverchallengeresp(pair_session_t &sess, pt::ptree &tree, const std::string &encrypted_response) {
if (sess.last_phase != PAIR_PHASE::CLIENTCHALLENGE) {
fail_pair(sess, tree, "Out of order call to serverchallengeresp");
@@ -451,6 +554,14 @@ namespace nvhttp {
tree.put("root.<xmlattr>.status_code", 200);
}
/**
* @brief Handle the client pairing-secret phase of GameStream pairing.
*
* @param sess Pairing session that owns the request state.
* @param add_cert Add cert.
* @param tree XML property tree used for the response body.
* @param client_pairing_secret Client pairing secret.
*/
void clientpairingsecret(pair_session_t &sess, std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, pt::ptree &tree, const std::string &client_pairing_secret) {
if (sess.last_phase != PAIR_PHASE::SERVERCHALLENGERESP) {
fail_pair(sess, tree, "Out of order call to clientpairingsecret");
@@ -504,16 +615,27 @@ namespace nvhttp {
template<class T>
struct tunnel;
/**
* @brief HTTPS tunnel session used for encrypted client requests.
*/
template<>
struct tunnel<SunshineHTTPS> {
static auto constexpr to_string = "HTTPS"sv;
static auto constexpr to_string = "HTTPS"sv; ///< To string.
};
/**
* @brief Plain HTTP server wrapper used for non-TLS endpoints.
*/
template<>
struct tunnel<SimpleWeb::HTTP> {
static auto constexpr to_string = "NONE"sv;
static auto constexpr to_string = "NONE"sv; ///< To string.
};
/**
* @brief Write req details to the log.
*
* @param request HTTP request data from the client.
*/
template<class T>
void print_req(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
BOOST_LOG(debug) << "TUNNEL :: "sv << tunnel<T>::to_string;
@@ -534,6 +656,12 @@ namespace nvhttp {
BOOST_LOG(debug) << " [--] "sv;
}
/**
* @brief Return a GameStream HTTP not-found response.
*
* @param response HTTP response object to populate.
* @param request HTTP request data from the client.
*/
template<class T>
void not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
print_req<T>(request);
@@ -553,6 +681,13 @@ namespace nvhttp {
response->close_connection_after_response = true;
}
/**
* @brief Dispatch the top-level GameStream pairing request by phase.
*
* @param add_cert Add cert.
* @param response HTTP response object to populate.
* @param request HTTP request data from the client.
*/
template<class T>
void pair(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
print_req<T>(request);
@@ -684,6 +819,11 @@ namespace nvhttp {
return true;
}
/**
* @brief Get codec mode flags.
*
* @return Moonlight codec capability bitmask for the currently probed encoders.
*/
uint32_t get_codec_mode_flags() {
uint32_t codec_mode_flags = SCM_H264;
if (video::last_encoder_probe_supported_yuv444_for_codec[0]) {
@@ -717,6 +857,12 @@ namespace nvhttp {
return codec_mode_flags;
}
/**
* @brief Build the GameStream server-info response.
*
* @param response HTTP response object to populate.
* @param request HTTP request data from the client.
*/
template<class T>
void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
print_req<T>(request);
@@ -801,6 +947,12 @@ namespace nvhttp {
return named_cert_nodes;
}
/**
* @brief Build the GameStream application list response.
*
* @param response HTTP response object to populate.
* @param request HTTP request data from the client.
*/
void applist(resp_https_t response, req_https_t request) {
print_req<SunshineHTTPS>(request);
@@ -829,6 +981,13 @@ namespace nvhttp {
}
}
/**
* @brief Launch the requested application for a GameStream session.
*
* @param host_audio Host audio.
* @param response HTTP response object to populate.
* @param request HTTP request data from the client.
*/
void launch(bool &host_audio, resp_https_t response, req_https_t request) {
print_req<SunshineHTTPS>(request);
@@ -940,6 +1099,13 @@ namespace nvhttp {
revert_display_configuration = false;
}
/**
* @brief Resume an existing GameStream session.
*
* @param host_audio Host audio.
* @param response HTTP response object to populate.
* @param request HTTP request data from the client.
*/
void resume(bool &host_audio, resp_https_t response, req_https_t request) {
print_req<SunshineHTTPS>(request);
@@ -1031,6 +1197,12 @@ namespace nvhttp {
rtsp_stream::launch_session_raise(launch_session);
}
/**
* @brief Check whether cel.
*
* @param response HTTP response object to populate.
* @param request HTTP request data from the client.
*/
void cancel(resp_https_t response, req_https_t request) {
print_req<SunshineHTTPS>(request);
@@ -1056,6 +1228,12 @@ namespace nvhttp {
display_device::revert_configuration();
}
/**
* @brief Return an application asset requested by the client.
*
* @param response HTTP response object to populate.
* @param request HTTP request data from the client.
*/
void appasset(resp_https_t response, req_https_t request) {
print_req<SunshineHTTPS>(request);
@@ -1074,6 +1252,12 @@ namespace nvhttp {
conf_intern.servercert = cert;
}
/**
* @brief Check whether a paired client certificate is allowed to connect.
*
* @param cert_pem PEM-encoded client certificate to look up.
* @return True when the client certificate belongs to an enabled device.
*/
bool is_client_enabled(const std::string_view cert_pem);
void start() {
@@ -1266,6 +1450,9 @@ namespace nvhttp {
return false;
}
/**
* @brief Get cert by UUID.
*/
std::string get_cert_by_uuid(const std::string_view uuid) {
for (const auto &named_cert : client_root.named_devices) {
if (named_cert.uuid == uuid) {
@@ -1275,6 +1462,9 @@ namespace nvhttp {
return {};
}
/**
* @brief Check whether a paired client certificate is allowed to connect.
*/
bool is_client_enabled(const std::string_view cert_pem) {
const client_t &client = client_root;
for (const auto &named_cert : client.named_devices) {