|
Sunshine master
Self-hosted game stream host for Moonlight.
|
Contains all the functions and variables related to the nvhttp (GameStream) server. More...
Classes | |
| struct | client_t |
| Persisted pairing data for one Moonlight client. More... | |
| struct | conf_intern_t |
| Internal HTTPS credential paths for the configuration server. More... | |
| struct | named_cert_t |
| Certificate entry associated with a client name and UUID. More... | |
| struct | pair_session_t |
| Pairing handshake state exchanged with a Moonlight client. More... | |
| class | SunshineHTTPS |
| Simple-Web-Server HTTPS backend configured for Sunshine certificate handling. More... | |
| class | SunshineHTTPSServer |
| HTTPS server backend that adds Sunshine's client-certificate verification. More... | |
| struct | tunnel |
| struct | tunnel< SimpleWeb::HTTP > |
| Plain HTTP server wrapper used for non-TLS endpoints. More... | |
| struct | tunnel< SunshineHTTPS > |
| HTTPS tunnel session used for encrypted client requests. More... | |
Typedefs | |
| using | http_server_t = SimpleWeb::Server<SimpleWeb::HTTP> |
| Plain HTTP server type used for GameStream endpoints without TLS. | |
| using | https_server_t = SunshineHTTPSServer |
| HTTPS server type used for GameStream endpoints requiring TLS. | |
| using | req_http_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTP>::Request> |
| Shared HTTP request object received by redirect and discovery handlers. | |
| using | req_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SunshineHTTPS>::Request> |
| Shared HTTPS request object received by GameStream handlers. | |
| using | resp_http_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTP>::Response> |
| Shared HTTP response object passed to redirect and discovery handlers. | |
| using | resp_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SunshineHTTPS>::Response> |
| Shared HTTPS response object passed to GameStream handlers. | |
Enumerations | |
| enum class | op_e { ADD , REMOVE } |
| Certificate operations supported by the pairing API. More... | |
| enum class | PAIR_PHASE { NONE , GETSERVERCERT , CLIENTCHALLENGE , SERVERCHALLENGERESP , CLIENTPAIRINGSECRET } |
| Enumerates supported pAIR PHASE options. More... | |
Functions | |
| void | add_authorized_client (const std::string &name, std::string &&cert) |
| Add authorized client data. | |
| void | appasset (resp_https_t response, req_https_t request) |
| Return an application asset requested by the client. | |
| void | applist (resp_https_t response, req_https_t request) |
| Build the GameStream application list response. | |
| void | cancel (resp_https_t response, req_https_t request) |
| Check whether cel. | |
| void | clientchallenge (pair_session_t &sess, boost::property_tree::ptree &tree, const std::string &challenge) |
| Pair, phase 2. | |
| void | clientchallenge (pair_session_t &sess, pt::ptree &tree, const std::string &challenge) |
| Handle the client-challenge phase of GameStream pairing. | |
| void | clientpairingsecret (pair_session_t &sess, std::shared_ptr< safe::queue_t< crypto::x509_t > > &add_cert, boost::property_tree::ptree &tree, const std::string &client_pairing_secret) |
| Pair, phase 4 (final) | |
| 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) |
| Handle the client pairing-secret phase of GameStream pairing. | |
| void | erase_all_clients () |
| Remove all paired clients. | |
| void | fail_pair (pair_session_t &sess, pt::ptree &tree, const std::string status_msg) |
| Return the GameStream pairing failure response. | |
| nlohmann::json | get_all_clients () |
| Get all paired clients. | |
| std::string | get_arg (const args_t &args, const char *name, const char *default_value=nullptr) |
| Read a named query argument from the HTTP request map. | |
| std::string | get_cert_by_uuid (const std::string_view uuid) |
| Get cert by UUID. | |
| uint32_t | get_codec_mode_flags () |
| Get codec mode flags. | |
| void | getservercert (pair_session_t &sess, boost::property_tree::ptree &tree, const std::string &pin) |
| Pair, phase 1. | |
| void | getservercert (pair_session_t &sess, pt::ptree &tree, const std::string &pin) |
| Return the server certificate text for pairing responses. | |
| bool | is_client_enabled (const std::string_view cert_pem) |
| Check whether a paired client certificate is allowed to connect. | |
| void | launch (bool &host_audio, resp_https_t response, req_https_t request) |
| Launch the requested application for a GameStream session. | |
| void | load_state () |
| Load state from its backing store. | |
| std::shared_ptr< rtsp_stream::launch_session_t > | make_launch_session (bool host_audio, const args_t &args) |
| Create launch session. | |
| template<class T > | |
| void | not_found (std::shared_ptr< typename SimpleWeb::ServerBase< T >::Response > response, std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > request) |
| Return a GameStream HTTP not-found response. | |
| 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) |
| Dispatch the top-level GameStream pairing request by phase. | |
| bool | pin (std::string pin, std::string name) |
| Compare the user supplied pin to the Moonlight pin. | |
| template<class T > | |
| void | print_req (std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > request) |
| Write req details to the log. | |
| void | remove_session (const pair_session_t &sess) |
| removes the temporary pairing session | |
| void | resume (bool &host_audio, resp_https_t response, req_https_t request) |
| Resume an existing GameStream session. | |
| void | save_state () |
| Persist the current state to its backing store. | |
| void | serverchallengeresp (pair_session_t &sess, boost::property_tree::ptree &tree, const std::string &encrypted_response) |
| Pair, phase 3. | |
| void | serverchallengeresp (pair_session_t &sess, pt::ptree &tree, const std::string &encrypted_response) |
| Handle the server-challenge response phase of GameStream pairing. | |
| template<class T > | |
| void | serverinfo (std::shared_ptr< typename SimpleWeb::ServerBase< T >::Response > response, std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > request) |
| Build the GameStream server-info response. | |
| bool | set_client_enabled (std::string_view uuid, bool enabled) |
| Enable or disable a client. | |
| void | setup (const std::string &pkey, const std::string &cert) |
| Setup the nvhttp server. | |
| void | start () |
| Start the nvhttp server. | |
| bool | unpair_client (std::string_view uuid) |
| Remove single client. | |
Variables | |
| crypto::cert_chain_t | cert_chain |
| Certificate chain presented by Sunshine's GameStream HTTPS server. | |
| client_t | client_root |
| In-memory representation of the paired-client database. | |
| struct nvhttp::conf_intern_t | conf_intern |
| TLS credential paths loaded from Sunshine's runtime configuration. | |
| constexpr auto | GFE_VERSION = "3.23.0.74" |
| The GFE version we are replicating. | |
| std::string | last_verified_client_cert |
| Last client certificate accepted by the TLS verify callback. // NOSONAR(cpp:S5421) - intentionally mutable global. | |
| std::unordered_map< std::string, pair_session_t > | map_id_sess |
| Pairing sessions keyed by temporary unique ID. | |
| constexpr auto | PORT_HTTP = 0 |
| The HTTP port, as a difference from the config port. | |
| constexpr auto | PORT_HTTPS = -5 |
| The HTTPS port, as a difference from the config port. | |
| std::atomic< uint32_t > | session_id_counter |
| Monotonic counter used to allocate GameStream session IDs. | |
| constexpr auto | VERSION = "7.1.431.-1" |
| The protocol version. | |
Contains all the functions and variables related to the nvhttp (GameStream) server.
|
strong |
|
strong |
Enumerates supported pAIR PHASE options.
| void nvhttp::add_authorized_client | ( | const std::string & | name, |
| std::string && | cert ) |
Add authorized client data.
| name | Human-readable name to assign. |
| cert | Certificate data or object used by the operation. |
| void nvhttp::appasset | ( | resp_https_t | response, |
| req_https_t | request ) |
Return an application asset requested by the client.
| response | HTTP response object to populate. |
| request | HTTP request data from the client. |
| void nvhttp::applist | ( | resp_https_t | response, |
| req_https_t | request ) |
Build the GameStream application list response.
| response | HTTP response object to populate. |
| request | HTTP request data from the client. |
| void nvhttp::cancel | ( | resp_https_t | response, |
| req_https_t | request ) |
Check whether cel.
| response | HTTP response object to populate. |
| request | HTTP request data from the client. |
| void nvhttp::clientchallenge | ( | pair_session_t & | sess, |
| boost::property_tree::ptree & | tree, | ||
| const std::string & | challenge ) |
Pair, phase 2.
Using the AES key that we generated in phase 1 we have to decrypt the client challenge,
We generate a SHA256 hash with the following:
The hash + server_challenge will then be AES encrypted and sent as the challengeresponse in the returned XML
| sess | Pairing session that owns the request state. |
| tree | XML property tree used for the response body. |
| challenge | Client challenge bytes from the pairing request. |
| void nvhttp::clientchallenge | ( | pair_session_t & | sess, |
| pt::ptree & | tree, | ||
| const std::string & | challenge ) |
Handle the client-challenge phase of GameStream pairing.
| sess | Pairing session that owns the request state. |
| tree | XML property tree used for the response body. |
| challenge | Client challenge bytes from the pairing request. |
| void nvhttp::clientpairingsecret | ( | pair_session_t & | sess, |
| std::shared_ptr< safe::queue_t< crypto::x509_t > > & | add_cert, | ||
| boost::property_tree::ptree & | tree, | ||
| const std::string & | client_pairing_secret ) |
Pair, phase 4 (final)
We now have to use everything we exchanged before in order to verify and finally pair the clients
We'll check the client_hash obtained at phase 3, it should contain the following:
Then using the client certificate public key we should be able to verify that the client secret has been signed by Moonlight
| sess | Pairing session that owns the request state. |
| add_cert | Add cert. |
| tree | XML property tree used for the response body. |
| client_pairing_secret | Client pairing secret. |
| void nvhttp::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 ) |
Handle the client pairing-secret phase of GameStream pairing.
| sess | Pairing session that owns the request state. |
| add_cert | Add cert. |
| tree | XML property tree used for the response body. |
| client_pairing_secret | Client pairing secret. |
| void nvhttp::erase_all_clients | ( | ) |
Remove all paired clients.
*Examples**
| void nvhttp::fail_pair | ( | pair_session_t & | sess, |
| pt::ptree & | tree, | ||
| const std::string | status_msg ) |
Return the GameStream pairing failure response.
| sess | Pairing session that owns the request state. |
| tree | XML property tree used for the response body. |
| status_msg | Status msg. |
| nlohmann::json nvhttp::get_all_clients | ( | ) |
Get all paired clients.
*Examples**
| std::string nvhttp::get_arg | ( | const args_t & | args, |
| const char * | name, | ||
| const char * | default_value = nullptr ) |
Read a named query argument from the HTTP request map.
| args | Parsed query-string argument map. |
| name | Query parameter name to read. |
| default_value | Value returned when the parameter is absent. |
| std::string nvhttp::get_cert_by_uuid | ( | std::string_view | uuid | ) |
Get cert by UUID.
| uuid | Client UUID being looked up or removed. |
| uint32_t nvhttp::get_codec_mode_flags | ( | ) |
Get codec mode flags.
| void nvhttp::getservercert | ( | pair_session_t & | sess, |
| boost::property_tree::ptree & | tree, | ||
| const std::string & | pin ) |
Pair, phase 1.
Moonlight will send a salt and client certificate, we'll also need the user provided pin.
PIN and SALT will be used to derive a shared AES key that needs to be stored in order to be used to decrypt_symmetric in the next phases.
At this stage we only have to send back our public certificate.
| sess | Pairing session that owns the request state. |
| tree | XML property tree used for the response body. |
| pin | PIN supplied by the client during pairing. |
| void nvhttp::getservercert | ( | pair_session_t & | sess, |
| pt::ptree & | tree, | ||
| const std::string & | pin ) |
Return the server certificate text for pairing responses.
| sess | Pairing session that owns the request state. |
| tree | XML property tree used for the response body. |
| pin | PIN supplied by the client during pairing. |
| bool nvhttp::is_client_enabled | ( | const std::string_view | cert_pem | ) |
Check whether a paired client certificate is allowed to connect.
| cert_pem | PEM-encoded client certificate to look up. |
| void nvhttp::launch | ( | bool & | host_audio, |
| resp_https_t | response, | ||
| req_https_t | request ) |
Launch the requested application for a GameStream session.
| host_audio | Host audio. |
| response | HTTP response object to populate. |
| request | HTTP request data from the client. |
| std::shared_ptr< rtsp_stream::launch_session_t > nvhttp::make_launch_session | ( | bool | host_audio, |
| const args_t & | args ) |
Create launch session.
| host_audio | Host audio. |
| args | Arguments forwarded to the callable or parser. |
| void nvhttp::not_found | ( | std::shared_ptr< typename SimpleWeb::ServerBase< T >::Response > | response, |
| std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > | request ) |
Return a GameStream HTTP not-found response.
| response | HTTP response object to populate. |
| request | HTTP request data from the client. |
| void nvhttp::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 ) |
Dispatch the top-level GameStream pairing request by phase.
| add_cert | Add cert. |
| response | HTTP response object to populate. |
| request | HTTP request data from the client. |
| bool nvhttp::pin | ( | std::string | pin, |
| std::string | name ) |
Compare the user supplied pin to the Moonlight pin.
| pin | The user supplied pin. |
| name | The user supplied name. |
true if the pin is correct, false otherwise.*Examples**
| void nvhttp::print_req | ( | std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > | request | ) |
Write req details to the log.
| request | HTTP request data from the client. |
| void nvhttp::remove_session | ( | const pair_session_t & | sess | ) |
removes the temporary pairing session
| sess |
| void nvhttp::resume | ( | bool & | host_audio, |
| resp_https_t | response, | ||
| req_https_t | request ) |
Resume an existing GameStream session.
| host_audio | Host audio. |
| response | HTTP response object to populate. |
| request | HTTP request data from the client. |
| void nvhttp::serverchallengeresp | ( | pair_session_t & | sess, |
| boost::property_tree::ptree & | tree, | ||
| const std::string & | encrypted_response ) |
Pair, phase 3.
Moonlight will send back a serverchallengeresp: an AES encrypted client hash, we have to send back the pairingsecret: using our private key we have to sign the certificate_signature + server_secret (generated in phase 2)
| sess | Pairing session that owns the request state. |
| tree | XML property tree used for the response body. |
| encrypted_response | Encrypted response. |
| void nvhttp::serverchallengeresp | ( | pair_session_t & | sess, |
| pt::ptree & | tree, | ||
| const std::string & | encrypted_response ) |
Handle the server-challenge response phase of GameStream pairing.
| sess | Pairing session that owns the request state. |
| tree | XML property tree used for the response body. |
| encrypted_response | Encrypted response. |
| void nvhttp::serverinfo | ( | std::shared_ptr< typename SimpleWeb::ServerBase< T >::Response > | response, |
| std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > | request ) |
Build the GameStream server-info response.
| response | HTTP response object to populate. |
| request | HTTP request data from the client. |
| bool nvhttp::set_client_enabled | ( | std::string_view | uuid, |
| bool | enabled ) |
Enable or disable a client.
| uuid | The UUID of the client. |
| enabled | Whether the client should be enabled. |
| void nvhttp::setup | ( | const std::string & | pkey, |
| const std::string & | cert ) |
Setup the nvhttp server.
| pkey | |
| cert |
| void nvhttp::start | ( | ) |
Start the nvhttp server.
*Examples**
| bool nvhttp::unpair_client | ( | std::string_view | uuid | ) |
Remove single client.
| uuid | The UUID of the client to remove. |
*Examples**
|
constexpr |
The protocol version.
The version of the GameStream protocol we are mocking.