docs(src): add examples alias and general cleanup (#2763)

This commit is contained in:
ReenigneArcher 2024-06-28 08:34:14 -04:00 • committed by GitHub
commit 1dd4b68e1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
142 changed files with 4216 additions and 1175 deletions

View file

@ -24,20 +24,25 @@
# must be first
DOXYFILE_ENCODING = UTF-8
# https://breathe.readthedocs.io/en/latest/markups.html#aliases
ALIASES = "rst=^^\verbatim embed:rst:leading-asterisk^^"
ALIASES += "endrst=\endverbatim"
ALIASES = ""
ALIASES += "examples=^^**Examples**^^@code{.cpp}"
ALIASES += "examples_end=@endcode^^"
ALIASES += "rst=^^\verbatim embed:rst:leading-asterisk^^"
ALIASES += "rst_end=\endverbatim"
CASE_SENSE_NAMES = YES
DISABLE_INDEX = NO
DOCBOOK_OUTPUT = doxydocbook
DOCSET_BUNDLE_ID = dev.lizardbyte.Sunshine
DOCSET_PUBLISHER_ID = dev.lizardbyte.Sunshine.documentation
DOCSET_PUBLISHER_NAME = LizardByte
DOT_GRAPH_MAX_NODES = 60
DOT_IMAGE_FORMAT = svg
# TODO: On Windows, Doxygen hangs when creating dot graphs if this is set to 0
DOT_NUM_THREADS = 1
EXTRACT_ALL = YES
FULL_SIDEBAR = NO
GENERATE_HTML = YES
GENERATE_LATEX = NO
@ -64,6 +69,14 @@ MACRO_EXPANSION = YES
MAN_OUTPUT = doxyman
NUM_PROC_THREADS = 1
PREDEFINED = DOXYGEN
PREDEFINED += __APPLE__
PREDEFINED += linux
PREDEFINED += __linux
PREDEFINED += __linux__
PREDEFINED += __MACH__
PREDEFINED += _WIN32
PREDEFINED += SUNSHINE_BUILD_WAYLAND
PREDEFINED += SUNSHINE_TRAY=1
PROJECT_BRIEF = "Self-hosted game stream host for Moonlight."
PROJECT_ICON = ../sunshine.ico
PROJECT_LOGO = ../sunshine.png
@ -79,4 +92,10 @@ WARN_AS_ERROR = FAIL_ON_WARNINGS
# TODO: Enable this when we have complete documentation
WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = YES
WARN_IF_INCOMPLETE_DOC = YES
WARN_IF_UNDOC_ENUM_VAL = YES
WARN_NO_PARAMDOC = YES
WARNINGS = YES
XML_OUTPUT = doxyxml

2894
docs/Doxyfile-1.10.0-default Normal file

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@
# standard imports
from datetime import datetime
import os
import shutil
import subprocess
from typing import Mapping, Optional
@ -148,6 +149,12 @@ for d in directories:
exist_ok=True,
)
# remove existing html files
# doxygen builds will not re-generated if the html directory already exists
html_dir = os.path.join(source_dir, 'build', 'html')
if os.path.exists(html_dir):
shutil.rmtree(html_dir)
# run doxygen
doxy_proc = _run_subprocess(
args_list=[doxygen_cmd, 'Doxyfile'],

View file

@ -1,66 +1,114 @@
Source Code
===========
We are in process of improving the source code documentation. Code should be documented using Doxygen syntax.
Some examples exist in `main.h` and `main.cpp`. In order for documentation within the code to appear in the
rendered docs, the definition of the object must be in a header file, although the documentation itself can (and
should) be in the source file.
Example Documentation Blocks
----------------------------
**file.h**
.. code-block:: c
// functions
int main(int argc, char *argv[]);
**file.cpp** (with markdown)
.. code-block:: cpp
/**
* @brief Main application entry point.
* @param argc The number of arguments.
* @param argv The arguments.
*
* EXAMPLES:
* ```cpp
* main(1, const char* args[] = {"hello", "markdown", nullptr});
* ```
*/
int main(int argc, char *argv[]) {
// do stuff
}
**file.cpp** (with ReStructuredText)
.. code-block:: cpp
/**
* @brief Main application entry point.
* @param argc The number of arguments.
* @param argv The arguments.
* @rst
* EXAMPLES:
*
* .. code-block:: cpp
* main(1, const char* args[] = {"hello", "rst", nullptr});
* @endrst
*/
int main(int argc, char *argv[]) {
// do stuff
}
Many examples exist throughout the codebase.
Source
------
For generated docs, refer to the `Doxygen Documentation <../doxyhtml/index.html>`_.
Please refer to the `Doxygen Documentation <../doxyhtml/index.html>`_ for more details.
Guidelines
----------
.. todo:: Sphinx and Breathe do not support the Objective-C Domain.
See https://github.com/breathe-doc/breathe/issues/129
Doxygen Comments
^^^^^^^^^^^^^^^^
.. .. doxygenindex::
.. :allow-dot-graphs:
- Use Doxygen comments to document all files, functions, classes, and variables.
- `Inline documentation block <Inline Documentation Blocks>`_ should use the following format:
.. Ideally, we would use `doxygenfile` with `:allow-dot-graphs:`, but sphinx complains about duplicated namespaces...
.. code-block:: cpp
///< A brief description of the member.
- Multi-line comments, such as for a `documentation block <Documentation Blocks>`_, should use the following format:
.. code-block:: cpp
/**
* @brief A brief description of the member.
* More detailed description of the member.
*/
Documentation Blocks
^^^^^^^^^^^^^^^^^^^^
Documentation blocks should be placed above the declaration of the function, class, or variable. Below is an example
of a documentation block for the main function.
.. code-block:: cpp
/**
* @brief Main application entry point.
* @param argc The number of arguments.
* @param argv The arguments.
* @return The exit code.
* @examples
* main(1, const char* args[] = {"hello", "markdown", nullptr});
* @end_examples
*/
int main(int argc, char *argv[]);
.. attention:: The `@examples` and `@end_examples` tags are not standard Doxygen tags. They are custom aliases
we have specified to simplify documenting examples. Do not confuse this with the standard `@example` tag.
In some cases, it could be valuable to have slightly different documentation for the definitions, especially when
the definition may change depending on the platform or other factors. In such cases, you should put the documentation
that is common in the declaration and the definition-specific documentation in the definition. Below is an example of
how to document the declaration and definition of a function.
.. code-block:: cpp
// myFile.h
/**
* @brief A brief description of the function.
* @param arg1 Describe the first argument.
* @param arg2 Describe the second argument.
* @return Describe the result.
*/
int myFunction(int arg1, int arg2);
// myFile.cpp
/**
* This describes anything which is specific to the implementation of the function.
*/
int myFunction(int arg1, int arg2)
{
// Implementation
}
File Documentation
^^^^^^^^^^^^^^^^^^
The file documentation block must be placed at the top of the file. If it is not present, Doxygen will ignore the file.
Understandably, it is difficult to make a creative description for every file although it is still required.
Below is an example of a file documentation block.
.. code-block:: cpp
/**
* @file src/main.cpp
* @brief Main application entry point.
*/
Inline Documentation Blocks
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Inline comments can be used to describe enum values, variables, and other code constructs.
To document the members of a file, struct, union, class, or enum, it is sometimes desired to place the documentation
block after the member instead of before. For this purpose you have to put an additional `<` marker in the comment
block. Below is an example of an inline comment for an enum value.
.. code-block:: cpp
enum class MyEnum
{
FIRST_VALUE, ///< A brief description of the FIRST_VALUE
SECOND_VALUE ///< A brief description of the SECOND_VALUE
};
Custom Aliases
^^^^^^^^^^^^^^
We have defined some custom aliases to simplify documenting examples.
- ``@examples`` - Start of an example block. This will format the following text as ``cpp``.
- ``@examples_end`` - End of an example block.
- ``@rst`` - Start of a reStructuredText block. This will format the following text as reStructuredText.
- ``@rst_end`` - End of a reStructuredText block.

View file

@ -1,6 +1,6 @@
/**
* @file src/audio.cpp
* @brief todo
* @brief Definitions for audio capture and encoding.
*/
#include <thread>

View file

@ -1,6 +1,6 @@
/**
* @file src/audio.h
* @brief todo
* @brief Declarations for audio capture and encoding.
*/
#pragma once
@ -8,13 +8,13 @@
#include "utility.h"
namespace audio {
enum stream_config_e : int {
STEREO,
HIGH_STEREO,
SURROUND51,
HIGH_SURROUND51,
SURROUND71,
HIGH_SURROUND71,
MAX_STREAM_CONFIG
STEREO, ///< Stereo
HIGH_STEREO, ///< High stereo
SURROUND51, ///< Surround 5.1
HIGH_SURROUND51, ///< High surround 5.1
SURROUND71, ///< Surround 7.1
HIGH_SURROUND71, ///< High surround 7.1
MAX_STREAM_CONFIG ///< Maximum audio stream configuration
};
struct opus_stream_config_t {
@ -37,10 +37,10 @@ namespace audio {
struct config_t {
enum flags_e : int {
HIGH_QUALITY,
HOST_AUDIO,
CUSTOM_SURROUND_PARAMS,
MAX_FLAGS
HIGH_QUALITY, ///< High quality audio
HOST_AUDIO, ///< Host audio
CUSTOM_SURROUND_PARAMS, ///< Custom surround parameters
MAX_FLAGS ///< Maximum number of flags
};
int packetDuration;

View file

@ -1,6 +1,6 @@
/**
* @file src/cbs.cpp
* @brief todo
* @brief Definitions for FFmpeg Coded Bitstream API.
*/
extern "C" {
#include <cbs/cbs_h264.h>
@ -217,6 +217,11 @@ namespace cbs {
};
}
/**
* This function initializes a Coded Bitstream Context and reads the packet into a Coded Bitstream Fragment.
* It then checks if the SPS->VUI (Video Usability Information) is present in the active SPS of the packet.
* This is done for both H264 and H265 codecs.
*/
bool
validate_sps(const AVPacket *packet, int codec_id) {
cbs::ctx_t ctx;

View file

@ -1,6 +1,6 @@
/**
* @file src/cbs.h
* @brief todo
* @brief Declarations for FFmpeg Coded Bitstream API.
*/
#pragma once
@ -31,7 +31,10 @@ namespace cbs {
make_sps_h264(const AVCodecContext *ctx, const AVPacket *packet);
/**
* Check if SPS->VUI is present
* @brief Validates the Sequence Parameter Set (SPS) of a given packet.
* @param packet The packet to validate.
* @param codec_id The ID of the codec used (either AV_CODEC_ID_H264 or AV_CODEC_ID_H265).
* @return True if the SPS->VUI is present in the active SPS of the packet, false otherwise.
*/
bool
validate_sps(const AVPacket *packet, int codec_id);

View file

@ -1,6 +1,6 @@
/**
* @file src/config.cpp
* @brief todo
* @brief Definitions for the configuration of Sunshine.
*/
#include <algorithm>
#include <filesystem>
@ -107,72 +107,72 @@ namespace config {
#endif
enum class quality_av1_e : int {
speed = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED,
quality = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY,
balanced = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED
speed = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED, ///< Speed preset
quality = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY, ///< Quality preset
balanced = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED ///< Balanced preset
};
enum class quality_hevc_e : int {
speed = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED,
quality = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY,
balanced = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED
speed = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED, ///< Speed preset
quality = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY, ///< Quality preset
balanced = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED ///< Balanced preset
};
enum class quality_h264_e : int {
speed = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED,
quality = AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY,
balanced = AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED
speed = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED, ///< Speed preset
quality = AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY, ///< Quality preset
balanced = AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED ///< Balanced preset
};
enum class rc_av1_e : int {
cbr = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR,
cqp = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP,
vbr_latency = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
vbr_peak = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR
cbr = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR, ///< CBR
cqp = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP, ///< CQP
vbr_latency = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, ///< VBR with latency constraints
vbr_peak = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR ///< VBR with peak constraints
};
enum class rc_hevc_e : int {
cbr = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR,
cqp = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP,
vbr_latency = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
vbr_peak = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR
cbr = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR, ///< CBR
cqp = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP, ///< CQP
vbr_latency = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, ///< VBR with latency constraints
vbr_peak = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR ///< VBR with peak constraints
};
enum class rc_h264_e : int {
cbr = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR,
cqp = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP,
vbr_latency = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
vbr_peak = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR
cbr = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR, ///< CBR
cqp = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP, ///< CQP
vbr_latency = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, ///< VBR with latency constraints
vbr_peak = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR ///< VBR with peak constraints
};
enum class usage_av1_e : int {
transcoding = AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING,
webcam = AMF_VIDEO_ENCODER_AV1_USAGE_WEBCAM,
lowlatency_high_quality = AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY_HIGH_QUALITY,
lowlatency = AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY,
ultralowlatency = AMF_VIDEO_ENCODER_AV1_USAGE_ULTRA_LOW_LATENCY
transcoding = AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING, ///< Transcoding preset
webcam = AMF_VIDEO_ENCODER_AV1_USAGE_WEBCAM, ///< Webcam preset
lowlatency_high_quality = AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY_HIGH_QUALITY, ///< Low latency high quality preset
lowlatency = AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY, ///< Low latency preset
ultralowlatency = AMF_VIDEO_ENCODER_AV1_USAGE_ULTRA_LOW_LATENCY ///< Ultra low latency preset
};
enum class usage_hevc_e : int {
transcoding = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING,
webcam = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM,
lowlatency_high_quality = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY,
lowlatency = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY,
ultralowlatency = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY
transcoding = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING, ///< Transcoding preset
webcam = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM, ///< Webcam preset
lowlatency_high_quality = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY, ///< Low latency high quality preset
lowlatency = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY, ///< Low latency preset
ultralowlatency = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY ///< Ultra low latency preset
};
enum class usage_h264_e : int {
transcoding = AMF_VIDEO_ENCODER_USAGE_TRANSCODING,
webcam = AMF_VIDEO_ENCODER_USAGE_WEBCAM,
lowlatency_high_quality = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY_HIGH_QUALITY,
lowlatency = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY,
ultralowlatency = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY
transcoding = AMF_VIDEO_ENCODER_USAGE_TRANSCODING, ///< Transcoding preset
webcam = AMF_VIDEO_ENCODER_USAGE_WEBCAM, ///< Webcam preset
lowlatency_high_quality = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY_HIGH_QUALITY, ///< Low latency high quality preset
lowlatency = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY, ///< Low latency preset
ultralowlatency = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY ///< Ultra low latency preset
};
enum coder_e : int {
_auto = AMF_VIDEO_ENCODER_UNDEFINED,
cabac = AMF_VIDEO_ENCODER_CABAC,
cavlc = AMF_VIDEO_ENCODER_CALV
_auto = AMF_VIDEO_ENCODER_UNDEFINED, ///< Auto
cabac = AMF_VIDEO_ENCODER_CABAC, ///< CABAC
cavlc = AMF_VIDEO_ENCODER_CALV ///< CAVLC
};
template <class T>
@ -226,19 +226,19 @@ namespace config {
namespace qsv {
enum preset_e : int {
veryslow = 1,
slower = 2,
slow = 3,
medium = 4,
fast = 5,
faster = 6,
veryfast = 7
veryslow = 1, ///< veryslow preset
slower = 2, ///< slower preset
slow = 3, ///< slow preset
medium = 4, ///< medium preset
fast = 5, ///< fast preset
faster = 6, ///< faster preset
veryfast = 7 ///< veryfast preset
};
enum cavlc_e : int {
_auto = false,
enabled = true,
disabled = false
_auto = false, ///< Auto
enabled = true, ///< Enabled
disabled = false ///< Disabled
};
std::optional<int>
@ -269,9 +269,9 @@ namespace config {
namespace vt {
enum coder_e : int {
_auto = 0,
cabac,
cavlc
_auto = 0, ///< Auto
cabac, ///< CABAC
cavlc ///< CAVLC
};
int

View file

@ -1,6 +1,6 @@
/**
* @file src/config.h
* @brief todo
* @brief Declarations for the configuration of Sunshine.
*/
#pragma once
@ -143,12 +143,12 @@ namespace config {
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
FORCE_VIDEO_HEADER_REPLACE, // force replacing headers inside video data
UPNP, // Try Universal Plug 'n Play
CONST_PIN, // Use "universal" pin
FLAG_SIZE
PIN_STDIN = 0, ///< Read PIN from stdin instead of http
FRESH_STATE, ///< Do not load or save state
FORCE_VIDEO_HEADER_REPLACE, ///< force replacing headers inside video data
UPNP, ///< Try Universal Plug 'n Play
CONST_PIN, ///< Use "universal" pin
FLAG_SIZE ///< Number of flags
};
}

View file

@ -1,10 +1,9 @@
/**
* @file src/confighttp.cpp
* @brief todo
* @brief Definitions for the Web UI Config HTTP server.
*
* @todo Authentication, better handling of routes common to nvhttp, cleanup
*/
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include "process.h"
@ -54,8 +53,8 @@ namespace confighttp {
using req_https_t = std::shared_ptr<typename SimpleWeb::ServerBase<SimpleWeb::HTTPS>::Request>;
enum class op_e {
ADD,
REMOVE
ADD, ///< Add client
REMOVE ///< Remove client
};
void
@ -156,7 +155,9 @@ namespace confighttp {
<< data.str();
}
// todo - combine these functions into a single function that accepts the page, i.e "index", "pin", "apps"
/**
* @todo combine these functions into a single function that accepts the page, i.e "index", "pin", "apps"
*/
void
getIndexPage(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return;
@ -255,10 +256,12 @@ namespace confighttp {
response->write(content, headers);
}
/**
* @todo combine function with getSunshineLogoImage and possibly getNodeModules
* @todo use mime_types map
*/
void
getFaviconImage(resp_https_t response, req_https_t request) {
// todo - combine function with getSunshineLogoImage and possibly getNodeModules
// todo - use mime_types map
print_req(request);
std::ifstream in(WEB_DIR "images/sunshine.ico", std::ios::binary);
@ -267,10 +270,12 @@ namespace confighttp {
response->write(SimpleWeb::StatusCode::success_ok, in, headers);
}
/**
* @todo combine function with getFaviconImage and possibly getNodeModules
* @todo use mime_types map
*/
void
getSunshineLogoImage(resp_https_t response, req_https_t request) {
// todo - combine function with getFaviconImage and possibly getNodeModules
// todo - use mime_types map
print_req(request);
std::ifstream in(WEB_DIR "images/logo-sunshine-45.png", std::ios::binary);

View file

@ -1,6 +1,6 @@
/**
* @file src/confighttp.h
* @brief todo
* @brief Declarations for the Web UI Config HTTP server.
*/
#pragma once

View file

@ -1,6 +1,6 @@
/**
* @file src/crypto.cpp
* @brief todo
* @brief Definitions for cryptography functions.
*/
#include "crypto.h"
#include <openssl/pem.h>
@ -30,7 +30,7 @@ namespace crypto {
// Expired or not-yet-valid certificates are fine. Sometimes Moonlight is running on embedded devices
// that don't have accurate clocks (or haven't yet synchronized by the time Moonlight first runs).
// This behavior also matches what GeForce Experience does.
// FIXME: Checking for X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY is a temporary workaround to get moonlight-embedded to work on the raspberry pi
// TODO: Checking for X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY is a temporary workaround to get moonlight-embedded to work on the raspberry pi
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_CERT_HAS_EXPIRED:
@ -42,11 +42,14 @@ namespace crypto {
}
/**
* @brief Verify the certificate chain.
* When certificates from two or more instances of Moonlight have been added to x509_store_t,
* only one of them will be verified by X509_verify_cert, resulting in only a single instance of
* Moonlight to be able to use Sunshine
*
* To circumvent this, x509_store_t instance will be created for each instance of the certificates.
* @param cert The certificate to verify.
* @return nullptr if the certificate is valid, otherwise an error string.
*/
const char *
cert_chain_t::verify(x509_t::element_type *cert) {
@ -176,6 +179,11 @@ namespace crypto {
return 0;
}
/**
* This function encrypts the given plaintext using the AES key in GCM mode. The initialization vector (IV) is also provided.
* The function handles the creation and initialization of the encryption context, and manages the encryption process.
* The resulting ciphertext and the GCM tag are written into the tagged_cipher buffer.
*/
int
gcm_t::encrypt(const std::string_view &plaintext, std::uint8_t *tagged_cipher, aes_t *iv) {
if (!encrypt_ctx && init_encrypt_gcm(encrypt_ctx, &key, iv, padding)) {
@ -267,6 +275,11 @@ namespace crypto {
return 0;
}
/**
* This function encrypts the given plaintext using the AES key in CBC mode. The initialization vector (IV) is also provided.
* The function handles the creation and initialization of the encryption context, and manages the encryption process.
* The resulting ciphertext is written into the cipher buffer.
*/
int
cbc_t::encrypt(const std::string_view &plaintext, std::uint8_t *cipher, aes_t *iv) {
if (!encrypt_ctx && init_encrypt_cbc(encrypt_ctx, &key, iv, padding)) {

View file

@ -1,6 +1,6 @@
/**
* @file src/crypto.h
* @brief todo
* @brief Declarations for cryptography functions.
*/
#pragma once
@ -126,10 +126,12 @@ namespace crypto {
gcm_t(const crypto::aes_t &key, bool padding = true);
/**
* @brief Encrypts the plaintext using AES GCM mode.
* length of cipher must be at least: round_to_pkcs7_padded(plaintext.size()) + crypto::cipher::tag_size
*
* return -1 on error
* return bytes written on success
* @param plaintext The plaintext data to be encrypted.
* @param tagged_cipher The buffer where the resulting ciphertext and GCM tag will be written.
* @param iv The initialization vector to be used for the encryption.
* @return The total length of the ciphertext and GCM tag written into tagged_cipher. Returns -1 in case of an error.
*/
int
encrypt(const std::string_view &plaintext, std::uint8_t *tagged_cipher, aes_t *iv);
@ -148,10 +150,12 @@ namespace crypto {
cbc_t(const crypto::aes_t &key, bool padding = true);
/**
* @brief Encrypts the plaintext using AES CBC mode.
* length of cipher must be at least: round_to_pkcs7_padded(plaintext.size())
*
* return -1 on error
* return bytes written on success
* @param plaintext The plaintext data to be encrypted.
* @param cipher The buffer where the resulting ciphertext will be written.
* @param iv The initialization vector to be used for the encryption.
* @return The total length of the ciphertext written into cipher. Returns -1 in case of an error.
*/
int
encrypt(const std::string_view &plaintext, std::uint8_t *cipher, aes_t *iv);

View file

@ -1,8 +1,7 @@
/**
* @file entry_handler.cpp
* @brief Entry point related functions.
* @brief Definitions for entry handling functions.
*/
// standard includes
#include <csignal>
#include <iostream>
@ -27,28 +26,12 @@ extern "C" {
using namespace std::literals;
/**
* @brief Launch the Web UI.
*
* EXAMPLES:
* ```cpp
* launch_ui();
* ```
*/
void
launch_ui() {
std::string url = "https://localhost:" + std::to_string(net::map_port(confighttp::PORT_HTTPS));
platf::open_url(url);
}
/**
* @brief Launch the Web UI at a specific endpoint.
*
* EXAMPLES:
* ```cpp
* launch_ui_with_path("/pin");
* ```
*/
void
launch_ui_with_path(std::string path) {
std::string url = "https://localhost:" + std::to_string(net::map_port(confighttp::PORT_HTTPS)) + path;
@ -56,22 +39,10 @@ launch_ui_with_path(std::string path) {
}
namespace args {
/**
* @brief Reset the user credentials.
*
* @param name The name of the program.
* @param argc The number of arguments.
* @param argv The arguments.
*
* EXAMPLES:
* ```cpp
* creds("sunshine", 2, {"new_username", "new_password"});
* ```
*/
int
creds(const char *name, int argc, char *argv[]) {
if (argc < 2 || argv[0] == "help"sv || argv[1] == "help"sv) {
help(name, argc, argv);
help(name);
}
http::save_user_creds(config::sunshine.credentials_file, argv[0], argv[1]);
@ -79,59 +50,21 @@ namespace args {
return 0;
}
/**
* @brief Print help to stdout, then exit.
* @param name The name of the program.
* @param argc The number of arguments. (Unused)
* @param argv The arguments. (Unused)
*
* EXAMPLES:
* ```cpp
* help("sunshine", 0, nullptr);
* ```
*/
int
help(const char *name, int argc, char *argv[]) {
help(const char *name) {
logging::print_help(name);
return 0;
}
/**
* @brief Print the version to stdout, then exit.
* @param name The name of the program. (Unused)
* @param argc The number of arguments. (Unused)
* @param argv The arguments. (Unused)
*
* EXAMPLES:
* ```cpp
* version("sunshine", 0, nullptr);
* ```
*/
int
version(const char *name, int argc, char *argv[]) {
version() {
// version was already logged at startup
return 0;
}
#ifdef _WIN32
/**
* @brief Restore global NVIDIA control panel settings.
*
* If Sunshine was improperly terminated, this function restores
* the global NVIDIA control panel settings to the undo file left
* by Sunshine. This function is typically called by the uninstaller.
*
* @param name The name of the program. (Unused)
* @param argc The number of arguments. (Unused)
* @param argv The arguments. (Unused)
*
* EXAMPLES:
* ```cpp
* restore_nvprefs_undo("sunshine", 0, nullptr);
* ```
*/
int
restore_nvprefs_undo(const char *name, int argc, char *argv[]) {
restore_nvprefs_undo() {
if (nvprefs_instance.load()) {
nvprefs_instance.restore_from_and_delete_undo_file_if_exists();
nvprefs_instance.unload();
@ -145,11 +78,6 @@ namespace lifetime {
char **argv;
std::atomic_int desired_exit_code;
/**
* @brief Terminates Sunshine gracefully with the provided exit code.
* @param exit_code The exit code to return from main().
* @param async Specifies whether our termination will be non-blocking.
*/
void
exit_sunshine(int exit_code, bool async) {
// Store the exit code of the first exit_sunshine() call
@ -166,9 +94,6 @@ namespace lifetime {
}
}
/**
* @brief Breaks into the debugger or terminates Sunshine if no debugger is attached.
*/
void
debug_trap() {
#ifdef _WIN32
@ -178,9 +103,6 @@ namespace lifetime {
#endif
}
/**
* @brief Gets the argv array passed to main().
*/
char **
get_argv() {
return argv;
@ -188,10 +110,6 @@ namespace lifetime {
} // namespace lifetime
#ifdef _WIN32
/**
* @brief Check if NVIDIA's GameStream software is running.
* @return `true` if GameStream is enabled, `false` otherwise.
*/
bool
is_gamestream_enabled() {
DWORD enabled;
@ -284,14 +202,6 @@ namespace service_ctrl {
SC_HANDLE service_handle = NULL;
};
/**
* @brief Check if the service is running.
*
* EXAMPLES:
* ```cpp
* is_service_running();
* ```
*/
bool
is_service_running() {
service_controller sc { SERVICE_QUERY_STATUS };
@ -304,14 +214,6 @@ namespace service_ctrl {
return status.dwCurrentState == SERVICE_RUNNING;
}
/**
* @brief Start the service and wait for startup to complete.
*
* EXAMPLES:
* ```cpp
* start_service();
* ```
*/
bool
start_service() {
service_controller sc { SERVICE_QUERY_STATUS | SERVICE_START };
@ -338,14 +240,6 @@ namespace service_ctrl {
return true;
}
/**
* @brief Wait for the UI to be ready after Sunshine startup.
*
* EXAMPLES:
* ```cpp
* wait_for_ui_ready();
* ```
*/
bool
wait_for_ui_ready() {
std::cout << "Waiting for Web UI to be ready...";

View file

@ -1,6 +1,6 @@
/**
* @file entry_handler.h
* @brief Header file for entry point functions.
* @brief Declarations for entry handling functions.
*/
#pragma once
@ -12,50 +12,138 @@
#include "thread_pool.h"
#include "thread_safe.h"
// functions
/**
* @brief Launch the Web UI.
* @examples
* launch_ui();
* @examples_end
*/
void
launch_ui();
/**
* @brief Launch the Web UI at a specific endpoint.
* @examples
* launch_ui_with_path("/pin");
* @examples_end
*/
void
launch_ui_with_path(std::string path);
#ifdef _WIN32
// windows only functions
bool
is_gamestream_enabled();
#endif
/**
* @brief Functions for handling command line arguments.
*/
namespace args {
/**
* @brief Reset the user credentials.
* @param name The name of the program.
* @param argc The number of arguments.
* @param argv The arguments.
* @examples
* creds("sunshine", 2, {"new_username", "new_password"});
* @examples_end
*/
int
creds(const char *name, int argc, char *argv[]);
/**
* @brief Print help to stdout, then exit.
* @param name The name of the program.
* @examples
* help("sunshine");
* @examples_end
*/
int
help(const char *name, int argc, char *argv[]);
help(const char *name);
/**
* @brief Print the version to stdout, then exit.
* @examples
* version();
* @examples_end
*/
int
version(const char *name, int argc, char *argv[]);
version();
#ifdef _WIN32
/**
* @brief Restore global NVIDIA control panel settings.
* If Sunshine was improperly terminated, this function restores
* the global NVIDIA control panel settings to the undo file left
* by Sunshine. This function is typically called by the uninstaller.
* @examples
* restore_nvprefs_undo();
* @examples_end
*/
int
restore_nvprefs_undo(const char *name, int argc, char *argv[]);
restore_nvprefs_undo();
#endif
} // namespace args
/**
* @brief Functions for handling the lifetime of Sunshine.
*/
namespace lifetime {
extern char **argv;
extern std::atomic_int desired_exit_code;
/**
* @brief Terminates Sunshine gracefully with the provided exit code.
* @param exit_code The exit code to return from main().
* @param async Specifies whether our termination will be non-blocking.
*/
void
exit_sunshine(int exit_code, bool async);
/**
* @brief Breaks into the debugger or terminates Sunshine if no debugger is attached.
*/
void
debug_trap();
/**
* @brief Get the argv array passed to main().
*/
char **
get_argv();
} // namespace lifetime
#ifdef _WIN32
/**
* @brief Check if NVIDIA's GameStream software is running.
* @return `true` if GameStream is enabled, `false` otherwise.
*/
bool
is_gamestream_enabled();
/**
* @brief Namespace for controlling the Sunshine service model on Windows.
*/
namespace service_ctrl {
/**
* @brief Check if the service is running.
* @examples
* is_service_running();
* @examples_end
*/
bool
is_service_running();
/**
* @brief Start the service and wait for startup to complete.
* @examples
* start_service();
* @examples_end
*/
bool
start_service();
/**
* @brief Wait for the UI to be ready after Sunshine startup.
* @examples
* wait_for_ui_ready();
* @examples_end
*/
bool
wait_for_ui_ready();
} // namespace service_ctrl

View file

@ -1,6 +1,6 @@
/**
* @file file_handler.cpp
* @brief File handling functions.
* @brief Definitions for file handling functions.
*/
// standard includes
@ -12,11 +12,6 @@
#include "logging.h"
namespace file_handler {
/**
* @brief Get the parent directory of a file or directory.
* @param path The path of the file or directory.
* @return `std::string` : The parent directory.
*/
std::string
get_parent_directory(const std::string &path) {
// remove any trailing path separators
@ -29,11 +24,6 @@ namespace file_handler {
return p.parent_path().string();
}
/**
* @brief Make a directory.
* @param path The path of the directory.
* @return `bool` : `true` on success, `false` on failure.
*/
bool
make_directory(const std::string &path) {
// first, check if the directory already exists
@ -44,16 +34,6 @@ namespace file_handler {
return std::filesystem::create_directories(path);
}
/**
* @brief Read a file to string.
* @param path The path of the file.
* @return `std::string` : The contents of the file.
*
* EXAMPLES:
* ```cpp
* std::string contents = read_file("path/to/file");
* ```
*/
std::string
read_file(const char *path) {
if (!std::filesystem::exists(path)) {
@ -65,17 +45,6 @@ namespace file_handler {
return std::string { (std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>() };
}
/**
* @brief Writes a file.
* @param path The path of the file.
* @param contents The contents to write.
* @return `int` : `0` on success, `-1` on failure.
*
* EXAMPLES:
* ```cpp
* int write_status = write_file("path/to/file", "file contents");
* ```
*/
int
write_file(const char *path, const std::string_view &contents) {
std::ofstream out(path);

View file

@ -1,21 +1,57 @@
/**
* @file file_handler.h
* @brief Header file for file handling functions.
* @brief Declarations for file handling functions.
*/
#pragma once
#include <string>
/**
* @brief Responsible for file handling functions.
*/
namespace file_handler {
/**
* @brief Get the parent directory of a file or directory.
* @param path The path of the file or directory.
* @return The parent directory.
* @examples
* std::string parent_dir = get_parent_directory("path/to/file");
* @examples_end
*/
std::string
get_parent_directory(const std::string &path);
/**
* @brief Make a directory.
* @param path The path of the directory.
* @return `true` on success, `false` on failure.
* @examples
* bool dir_created = make_directory("path/to/directory");
* @examples_end
*/
bool
make_directory(const std::string &path);
/**
* @brief Read a file to string.
* @param path The path of the file.
* @return The contents of the file.
* @examples
* std::string contents = read_file("path/to/file");
* @examples_end
*/
std::string
read_file(const char *path);
/**
* @brief Writes a file.
* @param path The path of the file.
* @param contents The contents to write.
* @return ``0`` on success, ``-1`` on failure.
* @examples
* int write_status = write_file("path/to/file", "file contents");
* @examples_end
*/
int
write_file(const char *path, const std::string_view &contents);
} // namespace file_handler

View file

@ -1,27 +1,13 @@
/**
* @file globals.cpp
* @brief Implementation for globally accessible variables and functions.
* @brief Definitions for globally accessible variables and functions.
*/
#include "globals.h"
/**
* @brief A process-wide communication mechanism.
*/
safe::mail_t mail::man;
/**
* @brief A thread pool for processing tasks.
*/
thread_pool_util::ThreadPool task_pool;
/**
* @brief A boolean flag to indicate whether the cursor should be displayed.
*/
bool display_cursor = true;
#ifdef _WIN32
/**
* @brief A global singleton used for NVIDIA control panel modifications.
*/
nvprefs::nvprefs_interface nvprefs_instance;
#endif

View file

@ -1,27 +1,44 @@
/**
* @file globals.h
* @brief Header for globally accessible variables and functions.
* @brief Declarations for globally accessible variables and functions.
*/
#pragma once
#include "entry_handler.h"
#include "thread_pool.h"
/**
* @brief A thread pool for processing tasks.
*/
extern thread_pool_util::ThreadPool task_pool;
/**
* @brief A boolean flag to indicate whether the cursor should be displayed.
*/
extern bool display_cursor;
#ifdef _WIN32
// Declare global singleton used for NVIDIA control panel modifications
#include "platform/windows/nvprefs/nvprefs_interface.h"
/**
* @brief A global singleton used for NVIDIA control panel modifications.
*/
extern nvprefs::nvprefs_interface nvprefs_instance;
#endif
/**
* @brief Handles process-wide communication.
*/
namespace mail {
#define MAIL(x) \
constexpr auto x = std::string_view { \
#x \
}
/**
* @brief A process-wide communication mechanism.
*/
extern safe::mail_t man;
// Global mail

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