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... | |
| struct | pairing_completion_t |
| Shared result used to return the completed pairing outcome to a PIN submitter. More... | |
| struct | pending_pairing_t |
| Operator-visible context for a pairing request awaiting PIN approval. 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 | args_t = SimpleWeb::CaseInsensitiveMultimap |
| Case-insensitive map used for HTTP headers and query parameters. | |
| 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... | |
| enum class | pair_session_insert_e { ADDED , ALREADY_EXISTS , FULL } |
| Result of inserting a new pairing session into bounded pending storage. More... | |
Functions | |
| std::string | 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. | |
| bool | cancel_pairing (std::string_view pairing_id) |
| Cancel a pairing request that is waiting for operator approval. | |
| std::string | canonical_certificate_pem (const std::string_view cert_pem) |
| Convert a PEM certificate to Sunshine's canonical OpenSSL serialization. | |
| std::mutex & | client_auth_mutex () |
| Get the mutex protecting paired-client authorization state. | |
| 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, boost::property_tree::ptree &tree, const std::string &client_pairing_secret) |
| Pair, phase 4 (final). | |
| void | clientpairingsecret (pair_session_t &sess, pt::ptree &tree, const std::string &client_pairing_secret) |
| Handle the client pairing-secret phase of GameStream pairing. | |
| void | complete_pairing (pair_session_t &sess, const bool success) |
| Publish the final result of a pairing handshake. | |
| void | erase_all_clients () |
| Remove all paired clients. | |
| bool | evict_abandoned_pair_session (const std::string &unique_id) |
| Evict an abandoned in-progress pairing session for a client. | |
| void | expire_pair_sessions (std::chrono::steady_clock::time_point now=std::chrono::steady_clock::now()) |
| Remove pairing sessions whose completion deadline has passed. | |
| void | expire_pair_sessions_unlocked (const std::chrono::steady_clock::time_point now) |
| Expire stale pairing sessions while the session mutex is held. | |
| 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. | |
| std::pair< bool, std::string > | get_client_status (const std::string_view cert_pem) |
| Check whether a paired client certificate is allowed to connect and retrieve its friendly name. | |
| uint32_t | get_codec_mode_flags () |
| Get codec mode flags. | |
| std::vector< pending_pairing_t > | get_pending_pairings () |
| List pairing requests that are waiting for operator PIN approval. | |
| 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. | |
| pair_session_insert_e | insert_pair_session (pair_session_t sess, std::string &pairing_id) |
| Insert a newly created pairing session into bounded pending storage. | |
| bool | is_client_enabled (const X509 *certificate) |
| Check whether a certificate exactly matches an enabled paired-client record. | |
| bool | is_valid_pairing_id (std::string_view pairing_id) |
| Validate an operator approval identifier received from the REST API. | |
| bool | is_valid_pairing_name (std::string_view name) |
| Validate an operator-supplied paired-client name received from the REST API. | |
| bool | is_valid_pairing_pin (std::string_view pin) |
| Validate a Moonlight pairing PIN received from the REST API. | |
| 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. | |
| std::mutex & | map_id_sess_mutex () |
| Get the mutex protecting pairing-session state. | |
| 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< 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_view pairing_id, std::string pin, std::string name) |
| Apply the user supplied PIN to the explicitly selected pairing request. | |
| template<class T> | |
| void | print_req (std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > request) |
| Write req details to the log. | |
| void | rebuild_client_cert_chain () |
| Rebuild the GameStream trust stores from enabled paired-client records. | |
| 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. | |
| template<class T> | |
| bool | start_pairing_session (const std::shared_ptr< typename SimpleWeb::ServerBase< T >::Response > &response, const std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > &request, const args_t &args, pt::ptree &tree, const std::string &unique_id) |
| Start a GameStream pairing session for a getservercert request. | |
| bool | unpair_client (std::string_view uuid) |
| Remove single client. | |
| const char * | verify_client_certificate (X509 *certificate) |
| Verify a client certificate against the exact enabled paired identity. | |
| bool | write_pairing_response (pair_session_t &sess, const pt::ptree &tree) |
| Write a completed response to the client waiting for PIN approval. | |
Variables | |
| crypto::cert_chain_t | cert_chain |
| Enabled paired-client certificates accepted by Sunshine's GameStream HTTPS server. | |
| client_t | client_root |
| In-memory representation of the paired-client database. | |
| 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::string | last_verified_client_name |
| Friendly name of last client certificate accepted by the TLS verify callback. // NOSONAR(cpp:S5421): intentionally mutable global. | |
| std::unordered_map< std::string, pair_session_t, util::transparent_string_hash, std::equal_to<> > | map_id_sess |
| Pairing sessions keyed by temporary unique ID. | |
| constexpr std::size_t | MAX_PAIRING_CLIENT_NAME_SIZE = 128 |
| Maximum number of bytes accepted for an operator-supplied paired-client name. | |
| constexpr std::size_t | MAX_PENDING_PAIRING_SESSIONS = 32 |
| Maximum number of pairing sessions retained at one time. | |
| constexpr std::size_t | PAIRING_ID_SIZE = 32 |
| Number of hexadecimal characters in an operator approval identifier. | |
| constexpr auto | PAIRING_SESSION_TIMEOUT = std::chrono::minutes {5} |
| Lifetime of an incomplete pairing session. | |
| 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.
|
strong |
| std::string nvhttp::add_authorized_client | ( | const std::string & | name, |
| std::string && | cert ) |
Add authorized client data.
A completed pairing replaces all records with the same exact X.509 identity so legacy duplicate records cannot make the newly paired client fail authorization.
| 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. |
| bool nvhttp::cancel_pairing | ( | std::string_view | pairing_id | ) |
Cancel a pairing request that is waiting for operator approval.
| pairing_id | Unguessable approval identifier returned by get_pending_pairings. |
| std::string nvhttp::canonical_certificate_pem | ( | const std::string_view | cert_pem | ) |
Convert a PEM certificate to Sunshine's canonical OpenSSL serialization.
| cert_pem | PEM-encoded certificate to canonicalize. |
| std::mutex & nvhttp::client_auth_mutex | ( | ) |
Get the mutex protecting paired-client authorization state.
| 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, |
| 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. |
| tree | XML property tree used for the response body. |
| client_pairing_secret | Client pairing secret. |
| void nvhttp::clientpairingsecret | ( | pair_session_t & | sess, |
| 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. |
| tree | XML property tree used for the response body. |
| client_pairing_secret | Client pairing secret. |
| void nvhttp::complete_pairing | ( | pair_session_t & | sess, |
| const bool | success ) |
Publish the final result of a pairing handshake.
| sess | Pairing session whose waiter should be notified. |
| success | Whether the client completed the authenticated handshake. |
| void nvhttp::erase_all_clients | ( | ) |
Remove all paired clients.
Examples
| bool nvhttp::evict_abandoned_pair_session | ( | const std::string & | unique_id | ) |
Evict an abandoned in-progress pairing session for a client.
A fresh getservercert request means the client abandoned its previous handshake and started over: the phase machine never accepts getservercert twice for one session, so the old handshake cannot resume. Evicting it lets the retry proceed instead of failing with 409 until the session expires. Sessions still waiting for operator PIN approval (last_phase == NONE) are left untouched, so a pending approval cannot be displaced by a stray getservercert. Eviction completes the old session as failed, waking any PIN submitter waiting on it, and orphans no live HTTP response: the response is consumed when PIN approval advances the session past the certificate phase.
| unique_id | Client-provided pairing-session identifier. |
| void nvhttp::expire_pair_sessions | ( | std::chrono::steady_clock::time_point | now = std::chrono::steady_clock::now() | ) |
Remove pairing sessions whose completion deadline has passed.
| now | Monotonic time used to evaluate session deadlines. |
| void nvhttp::expire_pair_sessions_unlocked | ( | const std::chrono::steady_clock::time_point | now | ) |
Expire stale pairing sessions while the session mutex is held.
| now | Monotonic time used to evaluate session deadlines. |
| 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. |
| std::pair< bool, std::string > nvhttp::get_client_status | ( | const std::string_view | cert_pem | ) |
Check whether a paired client certificate is allowed to connect and retrieve its friendly name.
Check whether a paired client certificate is allowed to connect and return its friendly name.
| cert_pem | PEM-encoded client certificate to look up. |
| uint32_t nvhttp::get_codec_mode_flags | ( | ) |
Get codec mode flags.
| std::vector< pending_pairing_t > nvhttp::get_pending_pairings | ( | ) |
List pairing requests that are waiting for operator PIN approval.
| 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. |
| pair_session_insert_e nvhttp::insert_pair_session | ( | pair_session_t | sess, |
| std::string & | pairing_id ) |
Insert a newly created pairing session into bounded pending storage.
| sess | Pairing session to insert. |
| pairing_id | Receives the unguessable approval identifier on success. |
| bool nvhttp::is_client_enabled | ( | const X509 * | certificate | ) |
Check whether a certificate exactly matches an enabled paired-client record.
| certificate | Parsed client certificate to compare by canonical X.509 identity. |
| bool nvhttp::is_valid_pairing_id | ( | std::string_view | pairing_id | ) |
Validate an operator approval identifier received from the REST API.
| pairing_id | Approval identifier to validate. |
| bool nvhttp::is_valid_pairing_name | ( | std::string_view | name | ) |
Validate an operator-supplied paired-client name received from the REST API.
| name | Client name to validate. |
| bool nvhttp::is_valid_pairing_pin | ( | std::string_view | pin | ) |
Validate a Moonlight pairing PIN received from the REST API.
| pin | PIN to validate. |
| 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. |
| std::mutex & nvhttp::map_id_sess_mutex | ( | ) |
Get the mutex protecting pairing-session state.
| 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< typename SimpleWeb::ServerBase< T >::Response > | response, |
| std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > | request ) |
Dispatch the top-level GameStream pairing request by phase.
| response | HTTP response object to populate. |
| request | HTTP request data from the client. |
| bool nvhttp::pin | ( | std::string_view | pairing_id, |
| std::string | pin, | ||
| std::string | name ) |
Apply the user supplied PIN to the explicitly selected pairing request.
| pairing_id | Unguessable identifier of the pairing request to approve. |
| pin | The user supplied pin. |
| name | The user supplied name. |
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::rebuild_client_cert_chain | ( | ) |
Rebuild the GameStream trust stores from enabled paired-client records.
| 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::start_pairing_session | ( | const std::shared_ptr< typename SimpleWeb::ServerBase< T >::Response > & | response, |
| const std::shared_ptr< typename SimpleWeb::ServerBase< T >::Request > & | request, | ||
| const args_t & | args, | ||
| pt::ptree & | tree, | ||
| const std::string & | unique_id ) |
Start a GameStream pairing session for a getservercert request.
| T | HTTP server transport type. |
| response | HTTP response retained while Web UI PIN approval is pending. |
| request | HTTP request containing the client pairing parameters. |
| args | Parsed request query parameters. |
| tree | XML property tree used for immediate responses. |
| unique_id | Client-provided pairing-session identifier. |
| bool nvhttp::unpair_client | ( | std::string_view | uuid | ) |
Remove single client.
| uuid | The UUID of the client to remove. |
Examples
| const char * nvhttp::verify_client_certificate | ( | X509 * | certificate | ) |
Verify a client certificate against the exact enabled paired identity.
| certificate | Parsed client certificate presented during the TLS handshake. |
| bool nvhttp::write_pairing_response | ( | pair_session_t & | sess, |
| const pt::ptree & | tree ) |
Write a completed response to the client waiting for PIN approval.
| sess | Pairing session that owns the waiting response. |
| tree | XML response body to write. |
|
constexpr |
The protocol version.
The version of the GameStream protocol we are mocking.